dlrNumeric/utilities.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLR_NUMERIC_UTILITIES_H_
00016 #define _DLR_NUMERIC_UTILITIES_H_
00017 
00018 #include <cmath>
00019 // #include <iostream>
00020 #include <cstdlib>
00021 
00022 #include <dlrCommon/tags.h>
00023 #include <dlrNumeric/numericTraits.h>
00024 #include <dlrNumeric/array1D.h>
00025 #include <dlrNumeric/array2D.h>
00026 #include <dlrNumeric/array3D.h>
00027 #include <dlrNumeric/index2D.h>
00028 #include <dlrNumeric/vector2D.h>
00029 #include <dlrNumeric/vector3D.h>
00030 
00031 namespace dlr {
00032 
00033   namespace numeric {
00034     
00035           namespace constants {
00036 
00037                   const double pi = 3.141592653589793238;
00038 
00039           } // nameapace contants
00040 
00053     template <class Type>
00054     Array1D<Type>
00055     abs(const Array1D<Type>& array0);
00056 
00057   
00070     template <class Type>
00071     Array2D<Type>
00072     abs(const Array2D<Type>& array0);
00073 
00074 
00084     template <class Type>
00085     bool
00086     allFalse(const Array1D<Type>& array0);
00087 
00088   
00098     template <class Type>
00099     bool
00100     allTrue(const Array1D<Type>& array0);
00101 
00102   
00112     template <class Type>
00113     inline bool
00114     anyFalse(const Array1D<Type>& array0);
00115 
00116   
00126     template <class Type>
00127     inline bool
00128     anyTrue(const Array1D<Type>& array0);
00129 
00130   
00141     template <class Type>
00142     inline size_t
00143     argmax(const Array1D<Type>& array0);
00144 
00145 
00167     template <class Type, class Functor>
00168     inline size_t
00169     argmax(const Array1D<Type>& array0, Functor comparator);
00170   
00171 
00182     template <class Type>
00183     inline size_t
00184     argmin(const Array1D<Type>& array0);
00185 
00186 
00204     template <class Type, class Functor>
00205     inline size_t
00206     argmin(const Array1D<Type>& array0, Functor comparator);
00207 
00208 
00220     template <class Type>
00221     Array1D<size_t>
00222     argsort(const Array1D<Type>& array0);
00223 
00224   
00225 //   /** 
00226 //    * This function returns an array of indices, result, so that the
00227 //    * sequence (array0[result[0]], array0[result[1]],
00228 //    * array0[result[2]], ...) is sorted from smallest to largest using
00229 //    * the supplied comparison operator.
00230 //    *
00231 //    * @param array0 The of this array will be compared to each other in
00232 //    * order to establish the correct sequence of indices.
00233 //    *
00234 //    * @param comparator This argument is a functor which supports the
00235 //    * std::binary_function<Type, Type, bool> interface, and returns
00236 //    * true if its first argument is smaller than its second argument.
00237 //    *
00238 //    * @return An array of indices as described above.
00239 //    */
00240 //   template <class Type, class Functor>
00241 //   Array1D<size_t>
00242 //   argsort(const Array1D<Type>& array0, Functor comparator);
00243 
00244   
00254     template <class Type>
00255     Array1D<Type>
00256     axisMax(const Array2D<Type>& array0,
00257             size_t axis) {return axisMaximum(array0, axis);}
00258 
00275     template <class Type>
00276     inline Array1D<Type>
00277     axisMaximum(const Array2D<Type>& array0, size_t axis);
00278 
00309     template <class Type, class Functor>
00310     Array1D<Type>
00311     axisMaximum(const Array2D<Type>& array0, size_t axis, Functor comparator);
00312 
00322     template <class Type>
00323     inline Array1D<Type>
00324     axisMin(const Array2D<Type>& array0,
00325             size_t axis) {return axisMinimum(array0, axis);}
00326   
00343     template <class Type>
00344     inline Array1D<Type>
00345     axisMinimum(const Array2D<Type>& array0, size_t axis);
00346 
00377     template <class Type, class Functor>
00378     Array1D<Type>
00379     axisMinimum(const Array2D<Type>& array0, size_t axis, Functor comparator);
00380 
00405     template <class Type>
00406     inline Array1D<typename NumericTraits<Type>::SumType>
00407     axisSum(const Array2D<Type>& array0, size_t axis);
00408 
00431     template <class Type, class ResultType>
00432     inline Array1D<ResultType>
00433     axisSum(const Array2D<Type>& array0, size_t axis,
00434             type_tag<ResultType> resultTag);
00435 
00475     template <class Type, class ResultType, class Functor>
00476     Array1D<ResultType>
00477     axisSum(const Array2D<Type>& array0, size_t axis,
00478             type_tag<ResultType> resultTag,
00479             const ResultType& initialValue, Functor adder);
00480 
00508     template <class Type>
00509     Array2D<Type>
00510     columnIndices(size_t rows, size_t columns, type_tag<Type> typeTag);
00511 
00543     template <class Type0, class Type1>
00544     inline Array1D<Type1>
00545     compress(const Array1D<Type0>& condition, const Array1D<Type1>& input);
00546 
00573     template <class Type0, class Type1>
00574     Array1D<Type1>
00575     compress(const Array1D<Type0>& condition, const Array1D<Type1>& input,
00576              size_t numTrue);
00577 
00578 
00589     template <class Type>
00590     inline size_t
00591     count(const Array1D<Type>& array0);
00592   
00606     inline Vector3D
00607     cross(const Vector3D& vector0, const Vector3D& vector1);
00608   
00620     template <class Type>
00621     inline typename NumericTraits<Type>::ProductType
00622     dot(const Array1D<Type>& array0, const Array1D<Type>& array1);
00623 
00638     template <class Type0, class Type1, class Type2>
00639     inline Type2
00640     dot(const Array1D<Type0>& array0, const Array1D<Type1>& array1,
00641         type_tag<Type2> typeTag);
00642 
00652     inline double
00653     dot(const Vector2D& vector0, const Vector2D& vector1);
00654 
00664     inline double
00665     dot(const Vector3D& vector0, const Vector3D& vector1);
00666 
00688     template <class Type>
00689     Array2D<Type>
00690     equivalentMatrix(const Array1D<Type>& vector0, size_t rowsInMatrix);
00691   
00692 
00715     template <class Type>
00716     void
00717     getMeanAndCovariance(const Array2D<Type>& sampleArray,
00718                          Array1D<double>& mean,
00719                          Array2D<double>& covariance,
00720                          size_t majorAxis=0);
00721   
00722                      
00740     template <class Type>
00741     Array2D<Type>
00742     identity(size_t rows, size_t columns, type_tag<Type> typeTag);
00743 
00744 
00754     template <class Type>
00755     Array1D<Type>
00756     ln(const Array1D<Type>& array0);
00757   
00758 
00768     template <class Type>
00769     Array2D<Type>
00770     ln(const Array2D<Type>& array0);
00771   
00772 
00793     template <class Type>
00794     Array2D<Type>
00795     logicalNot(const Array2D<Type>& array0);
00796 
00806     template <class Type>
00807     inline Type
00808     magnitude(const Array1D<Type>& array0);
00809 
00819     inline double
00820     magnitude(const Vector2D& vector0);
00821 
00831     inline double
00832     magnitude(const Vector3D& vector0);
00833 
00834   
00845     template <class Type>
00846     inline typename NumericTraits<Type>::ProductType
00847     magnitudeSquared(const Array1D<Type>& array0);
00848 
00849   
00860     inline double
00861     magnitudeSquared(const Vector2D& vector0);
00862 
00863   
00874     inline double
00875     magnitudeSquared(const Vector3D& vector0);
00876   
00877 
00895     template <class Type>
00896     inline Array1D<typename NumericTraits<Type>::ProductType>
00897     matrixMultiply(const Array1D<Type>& vector0, const Array2D<Type>& matrix0);
00898 
00916     template <class Type0, class Type1, class Type2>
00917     Array1D<Type2>
00918     matrixMultiply(const Array1D<Type0>& vector0, const Array2D<Type0>& matrix0,
00919                    type_tag<Type2> typeTag);
00920 
00937     template <class Type>
00938     inline Array1D<typename NumericTraits<Type>::ProductType>
00939     matrixMultiply(const Array2D<Type>& matrix0, const Array1D<Type>& vector0);
00940 
00958     template <class Type0, class Type1, class Type2>
00959     Array1D<Type2>
00960     matrixMultiply(const Array2D<Type0>& matrix0, const Array1D<Type1>& vector0,
00961                    type_tag<Type2> typeTag);
00962 
00963 
00978     template <class Type>
00979     inline Array2D<typename NumericTraits<Type>::ProductType>
00980     matrixMultiply(const Array2D<Type>& matrix0, const Array2D<Type>& matrix1);
00981     
00999     template <class Type0, class Type1, class Type2>
01000     Array2D<Type2>
01001     matrixMultiply(const Array2D<Type0>& matrix0, const Array2D<Type1>& matrix1,
01002                    type_tag<Type2> typeTag);
01003 
01004 
01005     // The next function is commented out because some environments use
01006     // #define directives for min() and max(), which don't obey
01007     // namespaces, and makes the code not compile if we define our own
01008     // min/max.
01009     // 
01010     // 
01011     // /** 
01012     // * This function is an alias for the function maximum(const
01013     // * Array1D&) below.
01014     // * 
01015     // * @param array0 See documentation for maximum(const Array1D&).
01016     // *
01017     // * @return See documentation for maximum(const Array1D&).
01018     // */
01019     // template <class Type>
01020     // inline Type
01021     // max(const Array1D<Type>& array0) {return maximum(array0);}
01022 
01032     template <class Type>
01033     inline Type
01034     maximum(const Array1D<Type>& array0);
01035 
01055     template <class Type, class Functor>
01056     Type
01057     maximum(const Array1D<Type>& array0, Functor comparator);
01058 
01059     
01071     template <class Iterator, class Type>
01072     Type
01073     mean(const Iterator& beginIter, const Iterator& endIter);
01074 
01075     
01087     template <class Type>
01088     inline double
01089     mean(const Array1D<Type>& array0);
01090 
01091     
01108     template <class Type0, class Type1>
01109     inline Type1
01110     mean(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01111   
01112 
01113     // The next function is commented out because some environments use
01114     // #define directives for min() and max(), which don't obey
01115     // namespaces, and makes the code not compile if we define our own
01116     // min/max.
01117     // 
01118     // 
01119     // /** 
01120     // * This function is an alias for the function minimum(const
01121     // * Array1D&) below.
01122     // * 
01123     // * @param array0 See documentation for minimum(const Array1D&).
01124     // *
01125     // * @return See documentation for minimum(const Array1D&).
01126     // */
01127     // template <class Type>
01128     // inline Type
01129     // min(const Array1D<Type>& array0) {return minimum(array0);}
01130 
01140     template <class Type>
01141     inline Type
01142     minimum(const Array1D<Type>& array0);
01143 
01163     template <class Type, class Functor>
01164     Type
01165     minimum(const Array1D<Type>& array0, Functor comparator);
01166 
01167 
01195     template <class FUNCTOR>
01196     double newtonRaphson(double startPoint, FUNCTOR objectiveFunction,
01197                          double epsilon, size_t maxIterations);
01198   
01220     template <class Type>
01221     inline double
01222     normalizedCorrelation(const Array1D<Type>& x, const Array1D<Type>& y);
01223 
01241     template <class Type, class Type2>
01242     Type2
01243     normalizedCorrelation(const Array1D<Type>& x, const Array1D<Type>& y,
01244                           type_tag<Type2> typeTag);
01245 
01258     template <class Type>
01259     inline Array1D<Type>
01260     ones(int size, type_tag<Type> typeTag);
01261 
01277     template <class Type>
01278     inline Array2D<Type>
01279     ones(int rows, int columns, type_tag<Type> typeTag);
01280 
01296     template <class Type>
01297     inline Array2D<typename NumericTraits<Type>::ProductType>
01298     outerProduct(const Array1D<Type>& array0, const Array1D<Type>& array1);
01299 
01319     template <class Type0, class Type1, class Type2>
01320     Array2D<Type2>
01321     outerProduct(const Array1D<Type0>& array0, const Array1D<Type1>& array1,
01322                  type_tag<Type2> typeTag);
01323 
01363     template <class Type>
01364     Array1D<Type>
01365     range(Type start, Type stop, Type stride=1);
01366 
01382     template <class Type>
01383     inline Array1D<Type>
01384     ravel(Array2D<Type>& inputArray) {return inputArray.ravel();}
01385 
01397     template <class Type>
01398     inline const Array1D<Type>
01399     ravel(const Array2D<Type>& inputArray) {return inputArray.ravel();}
01400 
01401 
01413     template <class Type>
01414     inline Type
01415     rms(const Array1D<Type>& array0);
01416 
01417 
01434     template <class Type0, class Type1>
01435     Type1
01436     rms(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01437 
01438 
01465     template <class Type>
01466     Array2D<Type>
01467     rowIndices(size_t rows, size_t columns, type_tag<Type> typeTag);
01468 
01469 
01484     template <class Type0, class Type1>
01485     inline bool
01486     shapeMatch(const Array1D<Type0>& array0, const Array1D<Type1>& array1);
01487 
01488 
01503     template <class Type0, class Type1>
01504     inline bool
01505     shapeMatch(const Array2D<Type0>& array0, const Array2D<Type1>& array1);
01506 
01507 
01522     template <class Type0, class Type1>
01523     inline bool
01524     shapeMatch(const Array3D<Type0>& array0, const Array3D<Type1>& array1);
01525 
01526 
01535     template <class Type>
01536     inline Array2D<Type>
01537     skewSymmetric(const Array1D<Type>& vector0);
01538 
01539 
01598     template <class Type>
01599     void
01600     solveQuadratic(Type c0, Type c1, Type c2,
01601                    Type& root0, Type& root1, bool& valid,
01602                    bool checkValidity=true);
01603 
01604   
01622     template <class Type>
01623     inline double
01624     standardDeviation(const Array1D<Type>& array0);
01625 
01649     template <class Type0, class Type1>
01650     inline Type1
01651     standardDeviation(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01652   
01653 
01663     template <class Type>
01664     inline typename NumericTraits<Type>::SumType
01665     sum(const Array1D<Type>& array0);
01666 
01667     
01681     template <class Type, class Type2>
01682     Type2
01683     sum(const Array1D<Type>& array0, type_tag<Type2> typeTag);
01684 
01685 
01706     template <class Type>
01707     inline typename NumericTraits<Type>::SumType
01708     sum(const Array2D<Type>& array0,
01709         const Index2D& upperLeftCorner,
01710         const Index2D& lowerRightCorner);
01711 
01712     
01737     template <class Type, class Type2>
01738     Type2
01739     sum(const Array2D<Type>& array0,
01740         const Index2D& upperLeftCorner,
01741         const Index2D& lowerRightCorner,
01742         type_tag<Type2> typeTag);
01743 
01744 
01762     template <class Type>
01763     inline double
01764     variance(const Array1D<Type>& array0);
01765 
01788     template <class Type0, class Type1>
01789     inline Type1
01790     variance(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01791 
01804     template <class Type>
01805     inline Array1D<Type>
01806     zeros(size_t size, type_tag<Type> typeTag);
01807 
01823     template <class Type>
01824     inline Array2D<Type>
01825     zeros(size_t rows, size_t columns, type_tag<Type> typeTag);
01826 
01845     template <class Type>
01846     inline Array3D<Type>
01847     zeros(size_t shape0, size_t shape1, size_t shape2, type_tag<Type> typeTag);
01848 
01849   } // namespace numeric
01850 
01851 } // namespace dlr
01852 
01853 
01854 /* ======= Declarations to maintain compatibility with legacy code. ======= */
01855 
01856 namespace dlr {
01857 
01858   using numeric::abs;
01859   using numeric::abs;
01860   using numeric::allFalse;
01861   using numeric::allTrue;
01862   using numeric::anyFalse;
01863   using numeric::anyTrue;
01864   using numeric::argmax;
01865   using numeric::argmin;
01866   using numeric::argsort;
01867   using numeric::axisMax;
01868   using numeric::axisMaximum;
01869   using numeric::axisMin;
01870   using numeric::axisMinimum;
01871   using numeric::axisSum;
01872   using numeric::columnIndices;
01873   using numeric::compress;
01874   using numeric::count;
01875   using numeric::cross;
01876   using numeric::dot;
01877   using numeric::equivalentMatrix;
01878   using numeric::getMeanAndCovariance;
01879   using numeric::identity;
01880   using numeric::ln;
01881   using numeric::logicalNot;
01882   using numeric::magnitude;
01883   using numeric::magnitudeSquared;
01884   using numeric::matrixMultiply;
01885   using numeric::maximum;
01886   using numeric::mean;
01887   using numeric::minimum;
01888   using numeric::newtonRaphson;
01889   using numeric::normalizedCorrelation;
01890   using numeric::ones;
01891   using numeric::outerProduct;
01892   using numeric::range;
01893   using numeric::ravel;
01894   using numeric::rms;
01895   using numeric::rowIndices;
01896   using numeric::shapeMatch;
01897   using numeric::skewSymmetric;
01898   using numeric::solveQuadratic;
01899   using numeric::standardDeviation;
01900   using numeric::sum;
01901   using numeric::variance;
01902   using numeric::zeros;
01903 
01904 } // namespace dlr
01905 
01906 
01907 /* ================ Definitions follow ================ */
01908 
01909 #include <cmath>
01910 #include <sstream>
01911 #include <numeric>
01912 //#include <algorithm>
01913 
01914 namespace dlr {
01915 
01916   namespace numeric {
01917     
01929     namespace privateCode {
01930 
01936       template <class Type>
01937       struct absFunctor : public std::unary_function<Type, Type> {
01945         inline Type operator()(const Type& input) {
01946           DLR_THROW3(NotImplementedException,
01947                      "absFunctor<Type>::operator()(const Type&)",
01948                      "absFunctor must be specialized for each type.");
01949           return static_cast<Type>(0);
01950         }
01951       };
01952 
01956       template <>
01957       struct absFunctor<long double>
01958         : public std::unary_function<long double, long double> {
01965         inline double operator()(const long double& input) {
01966           // fabsl doesn't appear to be commonly available.
01967           // return std::fabsl(input);
01968           return (input > 0.0) ? input : -input;
01969         }
01970       };
01971 
01972 
01976       template <>
01977       struct absFunctor<double> : public std::unary_function<double, double> {
01984         inline double operator()(const double& input) {
01985           return std::fabs(input);
01986         }
01987       };
01988 
01989 
01993       template <>
01994       struct absFunctor<float> : public std::unary_function<float, float> {
02001         inline float operator()(const float& input) {
02002           // Strange.  fabsf shows up in the global namespace.  Is this
02003           // a bug in the g++ 3.3 stand library?
02004           return fabsf(input);
02005         }
02006       };
02007 
02008 
02012       template <>
02013       struct absFunctor<long int>
02014         : public std::unary_function<long int, long int> {
02021         inline long int operator()(const long int& input) {
02022           return std::labs(input);
02023         }
02024       };
02025 
02026 
02030       template <>
02031       struct absFunctor<long long int>
02032         : public std::unary_function<long long int, long long int> {
02039         inline long long int operator()(const long long int& input) {
02040           // Many compilers don't support C99.
02041           // return std::llabs(input);
02042           return input >= 0LL ? input : -input;
02043         }
02044       };
02045 
02046 
02050       template <>
02051       struct absFunctor<int> : public std::unary_function<int, int> {
02058         inline int operator()(const int& input) {
02059           return std::abs(input);
02060         }
02061       };
02062 
02063 
02064     }
02068     // This function returns an array of the same size and element type
02069     // as its input argument, in which each element is set to the
02070     // absolute value of the corresponding element of the input array.
02071     template <class Type>
02072     Array1D<Type>
02073     abs(const Array1D<Type>& array0)
02074     {
02075       Array1D<Type> result(array0.size());
02076       std::transform(array0.begin(), array0.end(), result.begin(),
02077                      privateCode::absFunctor<Type>());
02078       return result;
02079     }
02080 
02081     // This function returns an array of the same size and element type
02082     // as its input argument, in which each element is set to the
02083     // absolute value of the corresponding element of the input array.
02084     template <class Type>
02085     Array2D<Type>
02086     abs(const Array2D<Type>& array0)
02087     {
02088       Array2D<Type> result(array0.rows(), array0.columns());
02089       std::transform(array0.begin(), array0.end(), result.begin(),
02090                      privateCode::absFunctor<Type>());
02091       return result;
02092     }
02093 
02094 
02095     // This function returns true if each element of its argument is
02096     // false, and returns false otherwise.
02097     template <class Type>
02098     bool
02099     allFalse(const Array1D<Type>& array0)
02100     {
02101       for(typename Array1D<Type>::const_iterator iter = array0.begin();
02102           iter != array0.end();
02103           ++iter) {
02104         if(*iter) {
02105           return false;
02106         }
02107       }
02108       return true;
02109     }
02110 
02111   
02112     // This function returns true if each element of its argument is
02113     // true, and returns false otherwise.
02114     template <class Type>
02115     bool
02116     allTrue(const Array1D<Type>& array0)
02117     {
02118       for(typename Array1D<Type>::const_iterator iter = array0.begin();
02119           iter != array0.end();
02120           ++iter) {
02121         if(!(*iter)) {
02122           return false;
02123         }
02124       }
02125       return true;
02126     }
02127 
02128   
02129     // This function returns true if any element of its argument is
02130     // false, and returns false otherwise.
02131     template <class Type>
02132     inline bool
02133     anyFalse(const Array1D<Type>& array0)
02134     {
02135       return !allTrue(array0);
02136     }
02137 
02138   
02139     // This function returns true if any element of its argument is
02140     // true, and returns false otherwise.
02141     template <class Type>
02142     inline bool
02143     anyTrue(const Array1D<Type>& array0)
02144     {
02145       return !allFalse(array0);
02146     }
02147 
02148   
02149     // This function returns the index of the largest element of its input
02150     // array.
02151     template <class Type>
02152     inline size_t
02153     argmax(const Array1D<Type>& array0) {
02154       return argmax(array0, std::less<Type>());
02155     }
02156 
02157 
02158     // This function returns the index of the largest element of its
02159     // input array, where largeness is defined by the second argument.
02160     template <class Type, class Functor>
02161     inline size_t
02162     argmax(const Array1D<Type>& array0, Functor comparator)
02163     {
02164       const Type* maxPtr = std::max_element(array0.begin(), array0.end(),
02165                                             comparator);
02166       return static_cast<size_t>(maxPtr - array0.begin());
02167     }
02168   
02169 
02170     // This function returns the index of the smallest element of its input
02171     // array.
02172     template <class Type>
02173     inline size_t
02174     argmin(const Array1D<Type>& array0)
02175     {
02176       return argmin(array0, std::less<Type>());
02177     }
02178 
02179 
02180     // This function returns the index of the smallest element of its
02181     // input array, where largeness is defined by the second argument.
02182     template <class Type, class Functor>
02183     inline size_t
02184     argmin(const Array1D<Type>& array0, Functor comparator)
02185     {
02186       const Type* minPtr = std::min_element(array0.begin(), array0.end(),
02187                                             comparator);
02188       return static_cast<size_t>(minPtr - array0.begin());
02189     }
02190 
02191 
02192     // This function returns an array of indices, result, so that the
02193     // sequence (array0[result[0]], array0[result[1]],
02194     // array0[result[2]], ...) is sorted from smallest to largest using
02195     // operator<().
02196     template <class Type>
02197     Array1D<size_t>
02198     argsort(const Array1D<Type>& array0)
02199     {
02200       Array1D< std::pair<Type, size_t> > sortVector(array0.size());
02201       Array1D<size_t> resultVector(array0.size());
02202 
02203       for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02204         sortVector[index0] = std::pair<Type, size_t>(array0[index0], index0);
02205       }
02206       std::sort(sortVector.begin(), sortVector.end());
02207       std::transform(sortVector.begin(), sortVector.end(), resultVector.begin(),
02208                      ExtractSecondFunctor<Type, size_t>());
02209       return resultVector;    
02210     }
02211 
02212   
02213 //   // This function returns an array of indices, result, so that the
02214 //   // sequence (array0[result[0]], array0[result[1]],
02215 //   // array0[result[2]], ...) is sorted from smallest to largest using
02216 //   // the supplied comparison operator.
02217 //   template <class Type, class Functor>
02218 //   Array1D<size_t>
02219 //   argsort(const Array1D<Type>& array0, Functor comparator)
02220 //   {
02221 //     Array1D< std::pair<Type, size_t> > sortVector(array0.size());
02222 //     Array1D<size_t> resultVector(array0.size());
02223 
02224 //     for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02225 //       sortVector[index0] = std::pair<Type, size_t>(array0[index0], index0);
02226 //     }
02227 //     std::sort(sortVector.begin(), sortVector.end(), comparator);
02228 //     std::transform(sortVector.begin(), sortVector.end(), resultVector.begin(),
02229 //                    ExtractSecondFunctor<Type, size_t>());
02230 //     return resultVector;    
02231 //   }
02232 
02233   
02234     // This function returns an Array1D in which each element has the
02235     // value of the largest element in one row or column of the input
02236     // Array2D.
02237     template <class Type>
02238     inline Array1D<Type>
02239     axisMaximum(const Array2D<Type>& array0, size_t axis)
02240     {
02241       return axisMaximum(array0, axis, std::less<Type>());
02242     }
02243 
02244 
02245     // This function returns an Array1D in which each element has the
02246     // value of the largest element in one row or column of the input
02247     // Array2D, where largeness is defined by the third argument.
02248     template <class Type, class Functor>
02249     Array1D<Type>
02250     axisMaximum(const Array2D<Type>& array0, size_t axis, Functor comparator)
02251     {
02252       Array1D<Type> result;
02253       switch(axis) {
02254       case 0:
02255         result.reinit(array0.columns());
02256         for(size_t column = 0; column < array0.columns(); ++column) {
02257           const Type* dataPtr = array0.data(0, column);
02258           Type columnMax = *dataPtr;
02259           size_t stride = array0.columns();
02260           for(size_t row = 0; row < array0.rows(); ++row) {
02261             if(!comparator(*dataPtr, columnMax)) {
02262               columnMax = *dataPtr;
02263             }
02264             dataPtr += stride;
02265           }
02266           result(column) = columnMax;
02267         }
02268         break;
02269       case 1:
02270         result.reinit(array0.rows());
02271         for(size_t row = 0; row < array0.rows(); ++row) {
02272           const Type* dataPtr = array0.data(row, 0);
02273           Type rowMax = *dataPtr;
02274           for(size_t column = 0; column < array0.columns(); ++column) {
02275             if(!comparator(*dataPtr, rowMax)) {
02276               rowMax = *dataPtr;
02277             }
02278             ++dataPtr;
02279           }
02280           result(row) = rowMax;
02281         }
02282         break;
02283       default:
02284         std::ostringstream message;
02285         message << "Axis " << axis << " is invalid for an Array2D.";
02286         DLR_THROW3(IndexException, "axisMaximum(const Array2D&, size_t, ...)",
02287                    message.str().c_str());
02288         break;
02289       }
02290       return result;  
02291     }
02292 
02293 
02294     // This function returns an Array1D in which each element has the
02295     // value of the smallest element in one row or column of the input
02296     // Array2D.
02297     template <class Type>
02298     inline Array1D<Type>
02299     axisMinimum(const Array2D<Type>& array0, size_t axis)
02300     {
02301       return axisMinimum(array0, axis, std::less<Type>());
02302     }
02303 
02304 
02305     // This function returns an Array1D in which each element has the
02306     // value of the smallest element in one row or column of the input
02307     // Array2D, where smallness is defined by the third argument.
02308     template <class Type, class Functor>
02309     Array1D<Type>
02310     axisMinimum(const Array2D<Type>& array0, size_t axis, Functor comparator)
02311     {
02312       Array1D<Type> result;
02313       switch(axis) {
02314       case 0:
02315         result.reinit(array0.columns());
02316         for(size_t column = 0; column < array0.columns(); ++column) {
02317           const Type* dataPtr = array0.data(0, column);
02318           Type columnMax = *dataPtr;
02319           size_t stride = array0.columns();
02320           for(size_t row = 0; row < array0.rows(); ++row) {
02321             if(comparator(*dataPtr, columnMax)) {
02322               columnMax = *dataPtr;
02323             }
02324             dataPtr += stride;
02325           }
02326           result(column) = columnMax;
02327         }
02328         break;
02329       case 1:
02330         result.reinit(array0.rows());
02331         for(size_t row = 0; row < array0.rows(); ++row) {
02332           const Type* dataPtr = array0.data(row, 0);
02333           Type rowMax = *dataPtr;
02334           for(size_t column = 0; column < array0.columns(); ++column) {
02335             if(comparator(*dataPtr, rowMax)) {
02336               rowMax = *dataPtr;
02337             }
02338             ++dataPtr;
02339           }
02340           result(row) = rowMax;
02341         }
02342         break;
02343       default:
02344         std::ostringstream message;
02345         message << "Axis " << axis << " is invalid for an Array2D.";
02346         DLR_THROW3(IndexException, "axisMinimum(const Array2D&, size_t, ...)",
02347                    message.str().c_str());
02348         break;
02349       }
02350       return result;  
02351     }
02352 
02353 
02354     // This function returns an Array1D in which each element has the
02355     // sum of one row or column of the input Array2D.
02356     template <class Type>
02357     inline Array1D<typename NumericTraits<Type>::SumType>
02358     axisSum(const Array2D<Type>& array0, size_t axis)
02359     {
02360       return axisSum(array0, axis,
02361                      type_tag<typename NumericTraits<Type>::SumType>());
02362     }
02363 
02364     // This function returns an Array1D in which each element has the
02365     // sum of one row or column of the input Array2D.
02366     template <class Type, class ResultType>
02367     inline Array1D<ResultType>
02368     axisSum(const Array2D<Type>& array0, size_t axis, type_tag<ResultType>)
02369     {
02370       return axisSum(array0, axis, type_tag<ResultType>(),
02371                      static_cast<ResultType>(0), std::plus<ResultType>());
02372     }
02373 
02374     // This function returns an Array1D in which each element has the
02375     // sum of one row or column of the input Array2D.
02376     template <class Type, class ResultType, class Functor>
02377     Array1D<ResultType>
02378     axisSum(const Array2D<Type>& array0, size_t axis, type_tag<ResultType>,
02379             const ResultType& initialValue, Functor adder)
02380     {
02381       Array1D<ResultType> result;
02382       switch(axis) {
02383       case 0:
02384         result.reinit(array0.columns());
02385         for(size_t column = 0; column < array0.columns(); ++column) {
02386           ResultType columnSum = initialValue;
02387           const Type* dataPtr = array0.data(0, column);
02388           size_t stride = array0.columns();
02389           for(size_t row = 0; row < array0.rows(); ++row) {
02390             columnSum = adder(columnSum, *dataPtr);
02391             dataPtr += stride;
02392           }
02393           result(column) = columnSum;
02394         }
02395         break;
02396       case 1:
02397         result.reinit(array0.rows());
02398         for(size_t row = 0; row < array0.rows(); ++row) {
02399           ResultType rowSum = initialValue;
02400           const Type* dataPtr = array0.data(row, 0);
02401           for(size_t column = 0; column < array0.columns(); ++column) {
02402             rowSum = adder(rowSum, *dataPtr);
02403             ++dataPtr;
02404           }
02405           result(row) = rowSum;
02406         }
02407         break;
02408       default:
02409         std::ostringstream message;
02410         message << "Axis " << axis << " is invalid for an Array2D.";
02411         DLR_THROW3(IndexException, "axisSum(const Array2D&, size_t, ...)",
02412                    message.str().c_str());
02413         break;
02414       }
02415       return result;  
02416     }
02417 
02418     // columnIndices(rows, columns): Returns an Array2D in which each
02419     // element contains the index of its column.
02420     template <class Type>
02421     Array2D<Type>
02422     columnIndices(size_t rows, size_t columns, type_tag<Type>)
02423     {
02424       Array2D<Type> returnValue(rows, columns);
02425       Array1D<Type> modelRow = range(static_cast<Type>(0),
02426                                      static_cast<Type>(columns),
02427                                      static_cast<Type>(1));
02428       for(size_t row=0; row < rows; ++row) {
02429         std::copy(modelRow.begin(), modelRow.end(), returnValue.data(row, 0));
02430       }
02431       return returnValue;
02432     }
02433 
02434     // This function selects those elements of an input Array1D which
02435     // correspond to "true" values of a mask Array1D, and returns an
02436     // Array1D containing only those elements.
02437     template <class Type0, class Type1>
02438     inline Array1D<Type1>
02439     compress(const Array1D<Type0>& condition,
02440              const Array1D<Type1>& input)
02441     {
02442       size_t numTrue = count(condition);
02443       return compress(condition, input, numTrue);
02444     }
02445 
02446     // This function behaves in exactly the same way as compress(const
02447     // Array1D&, const Array1D&), above, but it permits the user to
02448     // specify the number of true elements in the condition array.
02449     template <class Type0, class Type1>
02450     Array1D<Type1>
02451     compress(const Array1D<Type0>& condition,
02452              const Array1D<Type1>& input,
02453              size_t numTrue)
02454     {
02455       if(condition.size() != input.size()) {
02456         std::ostringstream message;
02457         message << "Condition and input arguments must have the same "
02458                 << "size, but condition has size = " << condition.size()
02459                 << ", while input has size = " << input.size() << ".";
02460         DLR_THROW3(ValueException,
02461                    "compress(const Array1D&, const Array1D&, size_t)",
02462                    message.str().c_str());
02463       }
02464       Array1D<Type1> result(numTrue);
02465       // copy_mask(input.begin(), input.end(), condition.begin(),
02466       //           result.begin());
02467       //
02468       // Hmm... copy_mask was previously defined in dlrLib3 as follows:
02469       //
02470       // template <class In0, class In1, class Out>
02471       // Out copy_mask(In0 first, In0 last, In1 mask, Out res)
02472       // {
02473       //   while(first != last) {
02474       //     if(*mask) {
02475       //       *res++ = *first;
02476       //     }
02477       //     ++mask;
02478       //     ++first;
02479       //   }
02480       //   return res;
02481       // }
02482 
02483       typename Array1D<Type1>::const_iterator first = input.begin();
02484       typename Array1D<Type1>::const_iterator last = input.end();
02485       typename Array1D<Type0>::const_iterator mask = condition.begin();
02486       typename Array1D<Type1>::iterator target = result.begin();
02487       while(first != last) {
02488         if(*mask) {
02489           *(target++) = *first;
02490         }
02491         ++mask;
02492         ++first;
02493       }
02494 
02495       return result;
02496     }
02497 
02498     // This element counts the number of elements of the input array
02499     // which evaluate to true, and returns that number.
02500     template <class Type>
02501     inline size_t
02502     count(const Array1D<Type>& x)
02503     {
02504       return std::count_if(x.begin(), x.end(), StaticCastFunctor<Type, bool>());
02505     }
02506 
02507     // This function computes the cross product of two Vector3D
02508     // instances.
02509     inline Vector3D
02510     cross(const Vector3D& vector0, const Vector3D& vector1) {
02511       return Vector3D((vector0.y() * vector1.z()) - (vector0.z() * vector1.y()),
02512                       (vector0.z() * vector1.x()) - (vector0.x() * vector1.z()),
02513                       (vector0.x() * vector1.y()) - (vector0.y() * vector1.x()));
02514     }
02515 
02516     // This function computes the inner product of two input arrays.
02517     // The computation is done using the ProductType specified by
02518     // the appropriate NumericTraits class.
02519     template <class Type>
02520     inline typename NumericTraits<Type>::ProductType
02521     dot(const Array1D<Type>& x, const Array1D<Type>& y)
02522     {
02523       return dot(x, y, type_tag<typename NumericTraits<Type>::ProductType>());
02524     }
02525 
02526     // This function computes the inner product of two input arrays, and
02527     // allows the user to control which type is used to do the
02528     // calculation.
02529     template <class Type0, class Type1, class Type2>
02530     inline Type2
02531     dot(const Array1D<Type0>& x, const Array1D<Type1>& y, type_tag<Type2>)
02532     {
02533       if(x.size() != y.size()) {
02534         std::ostringstream message;
02535         message << "Input arguments must have matching sizes, but x.size() == "
02536                 << x.size() << " and y.size() == " << y.size() << "."
02537                 << std::endl;
02538         DLR_THROW3(ValueException, "dot()", message.str().c_str());
02539       }
02540       return std::inner_product(x.begin(), x.end(), y.begin(),
02541                                 static_cast<Type2>(0));
02542     }
02543 
02544     // This function computes the inner product of two Vector2D instances.
02545     inline double
02546     dot(const Vector2D& vector0, const Vector2D& vector1)
02547     {
02548       return vector0.x() * vector1.x() + vector0.y() * vector1.y();
02549     }
02550 
02551     // This function computes the inner product of two Vector3D instances.
02552     inline double
02553     dot(const Vector3D& vector0, const Vector3D& vector1)
02554     {
02555       return (vector0.x() * vector1.x() + vector0.y() * vector1.y()
02556               + vector0.z() * vector1.z());
02557     }
02558 
02559     // This function computes the matrix X such that A * x = X * vec(A).
02560     template <class Type>
02561     Array2D<Type>
02562     equivalentMatrix(const Array1D<Type>& vector0, size_t rowsInMatrix)
02563     {
02564       Array2D<Type> XMatrix = zeros(rowsInMatrix, vector0.size() * rowsInMatrix,
02565                                     type_tag<Type>());
02566       for(size_t XRow = 0; XRow != rowsInMatrix; ++XRow) {
02567         for(size_t index0 = 0; index0 < vector0.length(); ++index0) {
02568           XMatrix(XRow, index0 * rowsInMatrix + XRow) = vector0(index0);
02569         }
02570       }
02571       return XMatrix;
02572     }
02573   
02574     // This function returns a 2D matrix with the specified shape in
02575     // which the elements on the diagonal are set to 1, and all other
02576     // elements are set to 0.
02577     template <class Type>
02578     Array2D<Type>
02579     identity(size_t rows, size_t columns, type_tag<Type>)
02580     {
02581       Array2D<Type> returnArray = zeros(rows, columns, type_tag<Type>());
02582       size_t rank = std::min(rows, columns);
02583       for(size_t index = 0; index < rank; ++index) {
02584         returnArray(index, index) = static_cast<Type>(1);
02585       } 
02586       return returnArray;
02587     }
02588 
02589 
02590     // This function returns an array in which each element is the
02591     // natural logarithm of the corresponding element of its input.
02592     template <class Type>
02593     Array1D<Type>
02594     ln(const Array1D<Type>& array0)
02595     {
02596       Array1D<Type> result(array0.size());
02597       // std::transform(array0.begin(), array0.end(), std::log);
02598       for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02599         result[index0] = std::log(array0[index0]);      
02600       }
02601       return result;
02602     }
02603 
02604 
02605 //   // Strange troubles compiling these next two functions.
02606 //
02607 //   // This function returns an array in which each element is the
02608 //   // natural logarithm of the corresponding element of its input.
02609 //   template <>
02610 //   Array1D<float>
02611 //   ln(const Array1D<float>& array0)
02612 //   {
02613 //     Array1D<float> result(array0.size());
02614 //     std::transform(array0.begin(), array0.end(), std::logf);
02615 //     return result;
02616 //   }
02617 
02618 
02619 //   // This function returns an array in which each element is the
02620 //   // natural logarithm of the corresponding element of its input.
02621 //   template <>
02622 //   Array1D<long double>
02623 //   ln(const Array1D<long double>& array0)
02624 //   {
02625 //     Array1D<long double> result(array0.size());
02626 //     std::transform(array0.begin(), array0.end(), std::logl);
02627 //     return result;
02628 //   }
02629 
02630 
02631     // This function returns an array in which each element is the
02632     // natural logarithm of the corresponding element of its input.
02633     template <class Type>
02634     Array2D<Type>
02635     ln(const Array2D<Type>& array0)
02636     {
02637       Array2D<Type> result(array0.size());
02638       // std::transform(array0.begin(), array0.end(), std::log);
02639       for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02640         result[index0] = std::log(array0[index0]);      
02641       }
02642       return result;
02643     }
02644 
02645 
02646     // This function returns an Array2D instance in which the value of
02647     // each element is the logical not of the corresponding element of
02648     // the input array.
02649     template <class Type>
02650     Array2D<Type>
02651     logicalNot(const Array2D<Type>& array0)
02652     {
02653       Array2D<Type> result(array0.rows(), array0.columns());
02654       std::transform(array0.begin(), array0.end(), result.begin(),
02655                      unaryComposeFunctor(StaticCastFunctor<bool, Type>(),
02656                                          std::logical_not<Type>()));
02657       return result;
02658     }
02659 
02660   
02661     // This function computes the magnitude of its input argument.
02662     template <class Type>
02663     inline Type
02664     magnitude(const Array1D<Type>& array0)
02665     {
02666       return static_cast<Type>(std::sqrt(magnitudeSquared(array0)));
02667     }
02668 
02669   
02670     // This function computes the magnitude of its input argument.
02671     inline double
02672     magnitude(const Vector2D& vector0) {
02673       return std::sqrt(magnitudeSquared(vector0));
02674     }
02675 
02676   
02677     // This function computes the magnitude of its input argument.
02678     inline double
02679     magnitude(const Vector3D& vector0) {
02680       return std::sqrt(magnitudeSquared(vector0));
02681     }
02682 
02683 
02684     // This function computes the square of the magnitude of its input
02685     // argument.
02686     template <class Type>
02687     inline typename NumericTraits<Type>::ProductType
02688     magnitudeSquared(const Array1D<Type>& array0)
02689     {
02690       typedef typename NumericTraits<Type>::ProductType ProductType;
02691       return std::inner_product(array0.begin(), array0.end(),
02692                                 array0.begin(), static_cast<ProductType>(0));
02693     }
02694 
02695 
02696     // This function computes the square of the magnitude of its input
02697     // argument.
02698     inline double
02699     magnitudeSquared(const Vector2D& vector0) {
02700       return (vector0.x() * vector0.x() + vector0.y() * vector0.y());
02701     }
02702 
02703   
02704     // This function computes the square of the magnitude of its input
02705     // argument.
02706     inline double
02707     magnitudeSquared(const Vector3D& vector0) {
02708       return (vector0.x() * vector0.x() + vector0.y() * vector0.y()
02709               + vector0.z() * vector0.z());
02710     }
02711 
02712   
02713     // This function computes a vector * matrix product.  Assuming the
02714     // first argument, vector0, represents a column vector and the
02715     // second argument, matrix0, represents a 2D array, then this function
02716     // computes the product:
02717     //   vector0' * matrix0
02718     // Where the single quote indicates transpose.
02719     template <class Type>
02720     inline Array1D<typename NumericTraits<Type>::ProductType>
02721     matrixMultiply(const Array1D<Type>& vector0, const Array2D<Type>& matrix0)
02722     {
02723       return matrixMultiply(
02724         vector0, matrix0, type_tag<typename NumericTraits<Type>::ProductType>());
02725     }
02726 
02727     // This function computes a vector * matrix product just like
02728     // matrixMultiply(const Array1D<Type>&, const Array2D<Type>&), above.
02729     // This function differs in that the element type of the return
02730     // value is set explicitly using a third argument.
02731     template <class Type0, class Type1, class Type2>
02732     Array1D<Type2>
02733     matrixMultiply(const Array1D<Type0>& vector0, const Array2D<Type0>& matrix0,
02734                    type_tag<Type2>)
02735     {
02736       if(vector0.size() != matrix0.rows()) {
02737         std::ostringstream message;
02738         message << "Can't left-multiply a "
02739                 << matrix0.rows() << " x " << matrix0.columns()
02740                 << " matrix by a " << vector0.size() << " element vector\n";
02741         DLR_THROW(ValueException, "matrixMultiply()", message.str().c_str());
02742       }
02743       Array1D<Type2> result = zeros(matrix0.columns(), type_tag<Type2>());
02744       size_t index = 0;
02745       for(size_t row = 0; row < matrix0.rows(); ++row) {
02746         for(size_t column = 0; column < matrix0.columns(); ++column) {
02747           result[column] += (static_cast<Type2>(vector0[row])
02748                              * static_cast<Type2>(matrix0[index]));
02749           ++index;
02750         }
02751       }
02752       return result;
02753     }
02754 
02755     // This function computes a matrix * vector product.  Assuming the
02756     // first argument, matrix0, represents a matrix, and the and the
02757     // second argument, vector0, represents a column vector, then this
02758     // function computes the product:
02759     //  matrix0 * vector0
02760     template <class Type>
02761     inline Array1D<typename NumericTraits<Type>::ProductType>
02762     matrixMultiply(const Array2D<Type>& matrix0, const Array1D<Type>& vector0)
02763     {
02764       return matrixMultiply(
02765         matrix0, vector0, type_tag<typename NumericTraits<Type>::ProductType>());
02766     }
02767 
02768 
02769     // This function computes a matrix * vector product just like
02770     // matrixMultiply(const Array2D<Type>&, const Array1D<Type>&), above.
02771     // This function differs in that the element type of the return
02772     // value is set explicitly using a third argument.
02773     template <class Type0, class Type1, class Type2>
02774     Array1D<Type2>
02775     matrixMultiply(const Array2D<Type0>& matrix0, const Array1D<Type1>& vector0,
02776                    type_tag<Type2>)
02777     {
02778       if(vector0.size() != matrix0.columns()) {
02779         std::ostringstream message;
02780         message << "matrixMultiply() -- can't right-multiply a "
02781                 << matrix0.rows() << " x " << matrix0.columns()
02782                 << " matrix by a " << vector0.size() << " element vector\n";
02783         DLR_THROW(ValueException, "matrixMultiply()", message.str().c_str());
02784       }
02785       Array1D<Type2> result(matrix0.rows());
02786       for(size_t row = 0; row < matrix0.rows(); ++row) {
02787         result[row] = dot(vector0, matrix0.row(row), type_tag<Type2>());
02788       }
02789       return result;
02790     }
02791 
02792     // This function computes a matrix * matrix product.  That is,
02793     // the elements of the resulting array are the dot products of the
02794     // rows of the first argument with the columns of the second argument.
02795     template <class Type>
02796     inline Array2D<typename NumericTraits<Type>::ProductType>
02797     matrixMultiply(const Array2D<Type>& matrix0, const Array2D<Type>& matrix1)
02798     {
02799       return matrixMultiply(
02800         matrix0, matrix1, type_tag<typename NumericTraits<Type>::ProductType>());
02801     }
02802     
02803     // This function computes a matrix * matrix product, just like
02804     // matrixMultiply(const Array2D<Type>&, const Array2D<Type>&), above.
02805     // This function differs in that the element type of the return
02806     // value is set explicitly using a third argument.
02807     template <class Type0, class Type1, class Type2>
02808     Array2D<Type2>
02809     matrixMultiply(const Array2D<Type0>& matrix0, const Array2D<Type1>& matrix1,
02810                    type_tag<Type2>)
02811     {
02812       if(matrix1.rows() != matrix0.columns()) {
02813         std::ostringstream message;
02814         message << "matrixMultiply() -- can't left-multiply a "
02815                 << matrix1.rows() << " x " << matrix1.columns()
02816                 << " matrix by a "
02817                 << matrix0.rows() << " x " << matrix0.columns()
02818                 << " matrix\n";
02819         DLR_THROW(ValueException, "matrixMultiply()", message.str().c_str());
02820       }
02821       Array2D<Type2> result = zeros(matrix0.rows(), matrix1.columns(),
02822                                     type_tag<Type2>());
02823       for(size_t resultRow = 0; resultRow < result.rows(); ++resultRow) {
02824         for(size_t resultColumn = 0; resultColumn < result.columns();
02825             ++resultColumn) {
02826           for(size_t index = 0; index < matrix0.columns(); ++index) {
02827             result(resultRow, resultColumn) +=
02828               (static_cast<Type2>(matrix0(resultRow, index))
02829                * static_cast<Type2>(matrix1(index, resultColumn)));
02830           }
02831         }
02832       }
02833       return result;
02834     }
02835 
02836     // This function returns a copy of the largest element in the input
02837     // Array1D instance.
02838     template <class Type>
02839     inline Type
02840     maximum(const Array1D<Type>& array0)
02841     {
02842       return maximum(array0, std::less<Type>());
02843     }
02844 
02845     // This function returns a copy of the largest element in the input
02846     // Array1D instance, where largeness is defined by the return value
02847     // of the second argument.
02848     template <class Type, class Functor>
02849     Type
02850     maximum(const Array1D<Type>& array0, Functor comparator)
02851     {
02852       if(array0.size() == 0) {
02853         DLR_THROW3(ValueException, "maximum()",
02854                    "Can't find the maximum element of an empty array.");
02855       }
02856       return *std::max_element(array0.begin(), array0.end(), comparator);
02857     }
02858 
02859 
02860     // This function computes the average value, or geometric mean, of
02861     // the elements of input sequence.
02862     template <class Iterator, class Type>
02863     Type
02864     mean(const Iterator& beginIter, const Iterator& endIter)
02865     {
02866       Type meanValue;
02867       size_t count = 0;
02868       while(beginIter != endIter) {
02869         meanValue += *beginIter;
02870         ++count;
02871         ++beginIter;
02872       }
02873       return meanValue / count;
02874     }
02875 
02876     
02877     // This function computes the average value, or geometric mean, of
02878     // the elements of its argument.
02879     template <class Type>
02880     inline double
02881     mean(const Array1D<Type>& array0)
02882     {
02883       if(array0.size() == 0) {
02884         DLR_THROW3(ValueException, "mean()",
02885                    "Can't find the mean of an empty array.");
02886       }
02887       NumericTypeConversionFunctor<typename NumericTraits<Type>::SumType,
02888         Type> functor;
02889       return functor(
02890         mean(array0, type_tag<typename NumericTraits<Type>::SumType>()));
02891     }
02892   
02893 
02894     // This function computes the average value, or geometric mean, of
02895     // the elements of its argument, and allows the user to specify the
02896     // precision with which the computation is carried out.
02897     template <class Type0, class Type1>
02898     inline Type1
02899     mean(const Array1D<Type0>& array0, type_tag<Type1>)
02900     {
02901       return sum(array0, type_tag<Type1>()) / static_cast<Type1>(array0.size());
02902     }
02903   
02904 
02905     // This function estimates the mean and covariance of a set of
02906     // vectors, which are represented by the rows (or columns) of the
02907     // input 2D array.
02908     template <class Type>
02909     void
02910     getMeanAndCovariance(const Array2D<Type>& sampleArray,
02911                          Array1D<double>& meanArray,
02912                          Array2D<double>& covarianceArray,
02913                          size_t majorAxis)
02914     {
02915       // Check input.
02916       if(sampleArray.size() == 0) {
02917         meanArray.reinit(0);
02918         covarianceArray.reinit(0, 0);
02919         return;
02920       }
02921 
02922       // Compute number of samples and sample dimensionality.
02923       size_t dimensionality;
02924       size_t numberOfSamples;
02925       if(majorAxis == 0) {
02926         dimensionality = sampleArray.columns();
02927         numberOfSamples = sampleArray.rows();
02928       } else {
02929         dimensionality = sampleArray.rows();
02930         numberOfSamples = sampleArray.columns();
02931       }
02932       
02933       // Now compute the mean value of the sample points.
02934       // For efficiency, we simultaneously compute covariance.
02935       // We make use of the identity:
02936       // 
02937       //   covariance = E[(x - u)*(x - u)^T] = E[x * x^T] - u * u^T
02938       // 
02939       // where E[.] denotes expected value and u is the mean.
02940       //
02941       // Note that the sample mean is an unbiased estimator for u, but
02942       // substituting the sample mean for u in the covariance equation
02943       // gives a biased estimator of covariance.  We resolve this by
02944       // using the unbiased estimator:
02945       //
02946       //   covariance = (1/(N-1))sum(x * x^T) - (N/(N-1)) * uHat * uHat^T
02947       //
02948       // where uHat is the sample mean.
02949 
02950       meanArray.reinit(dimensionality);
02951       meanArray = 0.0;
02952       covarianceArray.reinit(dimensionality, dimensionality);
02953       covarianceArray = 0.0;
02954       typename Array2D<Type>::const_iterator sampleIterator =
02955         sampleArray.begin();
02956 
02957       if(majorAxis == 0) {
02958         for(size_t rowIndex = 0; rowIndex < sampleArray.rows(); ++rowIndex) {
02959           for(size_t columnIndex = 0; columnIndex < sampleArray.columns();
02960               ++columnIndex) {
02961             // Update accumulator for mean.
02962             meanArray[columnIndex] += *sampleIterator;
02963 
02964             // Update accumulator for covariance.  We only compute the top
02965             // half of the covariance matrix for now, since it's symmetric.
02966             typename Array2D<Type>::const_iterator sampleIterator2 =
02967               sampleIterator;
02968             for(size_t covarianceIndex = columnIndex;
02969                 covarianceIndex < dimensionality;
02970                 ++covarianceIndex) {
02971               // Note(xxx): Should fix this to run faster.
02972               covarianceArray(columnIndex, covarianceIndex) +=
02973                 *sampleIterator * *sampleIterator2;
02974               ++sampleIterator2;
02975             }
02976             ++sampleIterator;
02977           }
02978         }
02979       } else {
02980         for(size_t rowIndex = 0; rowIndex < sampleArray.rows(); ++rowIndex) {
02981           for(size_t columnIndex = 0; columnIndex < sampleArray.columns();
02982               ++columnIndex) {
02983             // Update accumulator for mean.
02984             meanArray[rowIndex] += *sampleIterator;
02985 
02986             // Update accumulator for covariance.  We only compute the top
02987             // half of the covariance matrix for now, since it's symmetric.
02988             typename Array2D<Type>::const_iterator sampleIterator2 =
02989               sampleIterator;
02990             for(size_t covarianceIndex = rowIndex;
02991                 covarianceIndex < dimensionality;
02992                 ++covarianceIndex) {
02993               // Note(xxx): Should fix this to run faster.
02994               covarianceArray(rowIndex, covarianceIndex) +=
02995                 *sampleIterator * *sampleIterator2;
02996               sampleIterator2 += numberOfSamples;
02997             }
02998             ++sampleIterator;
02999           }
03000         }
03001       }
03002     
03003       // Finish up the computation of the mean.
03004       meanArray /= static_cast<double>(numberOfSamples);
03005 
03006       // Finish up the computation of the covariance matrix.
03007       for(size_t index0 = 0; index0 < dimensionality; ++index0) {
03008         for(size_t index1 = index0; index1 < dimensionality; ++index1) {
03009           // Add correction to the top half of the covariance matrix.
03010           covarianceArray(index0, index1) -=
03011             numberOfSamples * meanArray[index0] * meanArray[index1];
03012           covarianceArray(index0, index1) /= (numberOfSamples - 1);
03013 
03014           // And copy to the bottom half.
03015           if(index0 != index1) {
03016             covarianceArray(index1, index0) = covarianceArray(index0, index1);
03017           }
03018         }
03019       }
03020 
03021     }
03022   
03023                     
03024     // This function returns a copy of the smallest element in the input
03025     // Array1D instance.
03026     template <class Type>
03027     inline Type
03028     minimum(const Array1D<Type>& array0)
03029     {
03030       if(array0.size() == 0) {
03031         DLR_THROW3(ValueException, "minimum()",
03032                    "Can't find the minimum element of an empty array.");
03033       }
03034       return minimum(array0, std::less<Type>());
03035     }
03036 
03037     // This function returns a copy of the smallest element in the input
03038     // Array1D instance, where largeness is defined by the value of the
03039     // second argument.
03040     template <class Type, class Functor>
03041     Type
03042     minimum(const Array1D<Type>& array0, Functor comparator)
03043     {
03044       return *std::min_element(array0.begin(), array0.end(), comparator);
03045     }
03046 
03047 
03048     // This function uses the iterative method of Newton and Raphson to
03049     // search for a zero crossing of the supplied functor.
03050     template <class FUNCTOR>
03051     double newtonRaphson(double startPoint, FUNCTOR objectiveFunction,
03052                          double epsilon, size_t maxIterations)
03053     {
03054       double argument = startPoint;
03055       for(size_t count = 0; count < maxIterations; ++count) {
03056         double result = objectiveFunction(argument);
03057         if(std::fabs(result) < epsilon) {
03058           return argument;
03059         }
03060         double resultPrime = objectiveFunction.derivative(argument);
03061         if(resultPrime == 0.0) {
03062           DLR_THROW(ValueException, "newtonRaphson()", "Zero derivative.");
03063         }
03064         argument = argument - (result / resultPrime);
03065       }
03066       DLR_THROW(ValueException, "newtonRaphson()",
03067                 "Root finding failed to converge.");
03068       return 0.0;  // keep compiler happy
03069     }
03070 
03071     // This function computes the normalized correlation of two Array1D
03072     // arguments.
03073     template <class Type>
03074     inline double
03075     normalizedCorrelation(const Array1D<Type>& x, const Array1D<Type>& y)
03076     {
03077       return normalizedCorrelation(x, y, type_tag<double>());
03078     }
03079 
03080     // This function is equivalent to normalizedCorrelation(const
03081     // Array1D&, const Array1D&), except that the computation is carried
03082     // out using the type specified by the third argument.
03083     template <class Type, class Type2>
03084     Type2
03085     normalizedCorrelation(const Array1D<Type>& x, const Array1D<Type>& y,
03086                           type_tag<Type2>)
03087     {
03088       Array1D<Type2> x0(x.size());
03089       Array1D<Type2> y0(x.size());
03090       x0.copy(x);
03091       y0.copy(y);
03092       x0 -= mean(x0, type_tag<Type2>());
03093       y0 -= mean(y0, type_tag<Type2>());
03094       Type2 denominator = ::sqrt(sum(x0 * x0) * sum(y0 * y0));
03095       if(denominator == static_cast<Type2>(0)) {
03096         return static_cast<Type2>(1.0);
03097       }
03098       Type2 C = sum(x0 * y0) / denominator;
03099       return C;
03100     }
03101 
03102     // This function returns an Array1D of the specified size and type
03103     // in which the value of every element is initialized to 1.
03104     template <class Type>
03105     inline Array1D<Type>
03106     ones(int size, type_tag<Type>)
03107     {
03108       Array1D<Type> result(size);
03109       result = 1;
03110       return result;
03111     }
03112 
03113     // This function returns an Array2D of the specified size and type
03114     // in which the value of every element is initialized to one.
03115     template <class Type>
03116     inline Array2D<Type>
03117     ones(int rows, int columns, type_tag<Type>)
03118     {
03119       Array2D<Type> result(rows, columns);
03120       result = 1;
03121       return result;
03122     }
03123 
03124     // This function computes the outer product of two input Array1D
03125     // instances. 
03126     template <class Type>
03127     inline Array2D<typename NumericTraits<Type>::ProductType>
03128     outerProduct(const Array1D<Type>& x, const Array1D<Type>& y)
03129     {
03130       return outerProduct(
03131         x, y, type_tag<typename NumericTraits<Type>::ProductType>());
03132     }
03133 
03134     // This function computes the outer product of two input Array1D
03135     // instances and allows the user to control which type is used to do the
03136     // computation.
03137     template <class Type0, class Type1, class Type2>
03138     Array2D<Type2>
03139     outerProduct(const Array1D<Type0>& x, const Array1D<Type1>& y,
03140                  type_tag<Type2>)
03141     {
03142       Array2D<Type2> result(x.size(), y.size());
03143       typename Array2D<Type2>::iterator runningIterator = result.begin();
03144       typename Array1D<Type1>::const_iterator yBegin = y.begin();
03145       typename Array1D<Type1>::const_iterator yEnd = y.end();
03146       for(size_t index = 0; index < x.size(); ++index) {
03147         std::transform(yBegin, yEnd, runningIterator,
03148                        std::bind2nd(std::multiplies<Type2>(), x[index]));
03149         runningIterator += y.size();
03150       }
03151       return result;
03152     }
03153 
03154     // This function returns an Array1D in which the first element has
03155     // value equal to argument "start," and each subsequent element has
03156     // value equal to the previous element plus argument "stride."
03157     template <class Type>
03158     Array1D<Type>
03159     range(Type start, Type stop, Type stride)
03160     {
03161       if(stride == 0) {
03162         DLR_THROW3(ValueException, "range(Type, Type, Type)",
03163                    "Argument \"stride\" must not be equal to 0.");
03164       }
03165       int length = static_cast<int>((stop - start) / stride);
03166       if(stride > 0) {
03167         if((length * stride) < (stop - start)) {      
03168           ++length;      
03169         }
03170       } else {
03171         if((length * stride) > (stop - start)) {
03172           ++length;      
03173         }
03174       }
03175       Array1D<Type> result(length);
03176       for(int index = 0; index < length; ++index) {
03177         result(index) = start;
03178         start += stride;
03179       }
03180       return result;
03181     }
03182   
03183 
03184     // This function computes the RMS (Root Mean Square) value of the
03185     // elements of its argument.
03186     template <class Type>
03187     inline Type
03188     rms(const Array1D<Type>& array0)
03189     {
03190       NumericTypeConversionFunctor<
03191         typename NumericTraits<Type>::SumType, Type> functor;
03192       return functor(rms(array0,
03193                          type_tag<typename NumericTraits<Type>::ProductType>()));
03194     }
03195 
03196     // This function computes the RMS (Root Mean Square) value of the
03197     // elements of its argument, and allows the user to specify the
03198     // precision with which the computation is carried out.
03199     template <class Type0, class Type1>
03200     Type1
03201     rms(const Array1D<Type0>& array0, type_tag<Type1>)
03202     {
03203       Type1 accumulator = 0;
03204       for(int index = 0; index < array0.size(); ++index) {
03205         Type1 element = static_cast<Type1>(array0[index]);
03206         accumulator += element * element;
03207       }
03208       return ::sqrt(accumulator / static_cast<Type1>(array0.size()));
03209     }
03210 
03211     // rowIndices(rows, columns): Returns an Array2D in which each
03212     // element contains the index of its row.
03213     template <class Type>
03214     Array2D<Type>
03215     rowIndices(size_t rows, size_t columns, type_tag<Type>)
03216     {
03217       Array2D<Type> returnValue(rows, columns);
03218       for(size_t row=0; row < rows; ++row) {
03219         Type* rowPtr = returnValue.data(row, 0);
03220         std::fill(rowPtr, rowPtr + columns, static_cast<Type>(row));
03221       }
03222       return returnValue;
03223     }
03224 
03225     // This function returns true if the two arrays have the same shape,
03226     // false otherwise.
03227     template <class Type0, class Type1>
03228     inline bool
03229     shapeMatch(const Array1D<Type0>& array0, const Array1D<Type1>& array1)
03230     {
03231       return array0.size() == array1.size();
03232     }
03233 
03234     // This function returns true if the two arrays have the same shape,
03235     // false otherwise.
03236     template <class Type0, class Type1>
03237     inline bool
03238     shapeMatch(const Array2D<Type0>& array0, const Array2D<Type1>& array1)
03239     {
03240       return ((array0.rows() == array1.rows())
03241               && (array0.columns() == array1.columns()));
03242     }
03243 
03244     // This function returns true if the two arrays have the same shape,
03245     // false otherwise.
03246     template <class Type0, class Type1>
03247     inline bool
03248     shapeMatch(const Array3D<Type0>& array0, const Array3D<Type1>& array1)
03249     {
03250       return ((array0.shape0() == array1.shape0())
03251               && (array0.shape1() == array1.shape1())
03252               && (array0.shape2() == array1.shape2()));            
03253     }
03254 
03255     // skewSymmetric(x): Returns a skew symmetric matrix X such
03256     // that matrixMultiply(X, y) = cross(x, y).
03257     template <class Type>
03258     inline Array2D<Type>
03259     skewSymmetric(const Array1D<Type>& vector0)
03260     {
03261       if(vector0.size() != 3) {
03262         std::ostringstream message;
03263         message << "Argument must have exactly 3 elements, but instead has "
03264                 << vector0.size() << "elements.";
03265         DLR_THROW(ValueException, "skewSymmetric()", message.str().c_str());
03266       }
03267       Array2D<Type> returnVal(3, 3);
03268       returnVal(0, 0) = 0;
03269       returnVal(0, 1) = -vector0(2);
03270       returnVal(0, 2) = vector0(1);
03271   
03272       returnVal(1, 0) = vector0(2);
03273       returnVal(1, 1) = 0;
03274       returnVal(1, 2) = -vector0(0);
03275 
03276       returnVal(2, 0) = -vector0(1);
03277       returnVal(2, 1) = vector0(0);
03278       returnVal(2, 2) = 0;
03279       return returnVal;
03280     }
03281 
03282 
03283     // This function computes the real roots of the quadratic polynomial
03284     // c0*x^2 + c1*x + c0 = 0.
03285     template <class Type>
03286     void
03287     solveQuadratic(Type c0, Type c1, Type c2,
03288                    Type& root0, Type& root1, bool& valid,
03289                    bool checkValidity)
03290     {
03291       Type ss = c1 * c1;
03292       ss -= (4.0 * c0 * c2);
03293       if(checkValidity) {
03294         valid = (ss >= 0.0);
03295         // s = numpy.choose(valid, (1.0, s))
03296         if(!valid) {
03297           ss = 1.0;
03298         }
03299       } else {
03300         valid = true;
03301       }
03302       Type rt = std::sqrt(ss);
03303       // sgn = numpy.greater_equal(b, 0.0)
03304       // rt = numpy.choose(sgn, (-rt, rt))
03305       if(c1 < 0.0) {
03306         rt *= -1;
03307       }
03308       Type qq = -0.5 * (rt + c1);
03309       root0 = qq / c0;
03310       root1 = c2 / qq;
03311     }
03312 
03313   
03314     // This function computes the standard deviation of a group of
03315     // scalar samples.
03316     template <class Type>
03317     inline double
03318     standardDeviation(const Array1D<Type>& array0)
03319     {
03320       return standardDeviation(array0, type_tag<double>());
03321     }
03322 
03323     // This function computes the standard deviation, of the elements of
03324     // its argument, and allows the user to specify the precision with
03325     // which the computation is carried out.
03326     template <class Type0, class Type1>
03327     inline Type1
03328     standardDeviation(const Array1D<Type0>& array0, type_tag<Type1>)
03329     {
03330       return ::sqrt(variance(array0, type_tag<Type1>()));
03331     }
03332 
03333     // This function computes the sum of all elements in the input
03334     // array.  The summation is done using the SumType specified by the
03335     // appropriate NumericTraits class.
03336     template <class Type>
03337     inline typename NumericTraits<Type>::SumType
03338     sum(const Array1D<Type>& array0)
03339     {
03340       return sum(array0, type_tag<typename NumericTraits<Type>::SumType>());
03341     }
03342 
03343     // This function computes the sum of all elements in the input
03344     // array, and allows the user to control which type is used to do the
03345     // summation.
03346     template <class Type, class Type2>
03347     Type2
03348     sum(const Array1D<Type>& array0, type_tag<Type2>)
03349     {
03350       return std::accumulate(array0.begin(), array0.end(),
03351                              static_cast<Type2>(0));
03352     }
03353 
03354 
03355     // This function computes the sum of those elements of its
03356     // argument which lie within a rectangular region of interest.
03357     template <class Type>
03358     inline typename NumericTraits<Type>::SumType
03359     sum(const Array2D<Type>& array0,
03360         const Index2D& upperLeftCorner,
03361         const Index2D& lowerRightCorner)
03362     {
03363       return sum(array0, upperLeftCorner, lowerRightCorner,
03364                  type_tag<typename NumericTraits<Type>::SumType>());
03365     }
03366       
03367     
03368     // This function computes the sum of those elements of its
03369     // argument which lie within a rectangular region of interest.
03370     template <class Type, class Type2>
03371     Type2
03372     sum(const Array2D<Type>& array0,
03373         const Index2D& upperLeftCorner,
03374         const Index2D& lowerRightCorner,
03375         type_tag<Type2> typeTag)
03376     {
03377       Type2 result = static_cast<Type2>(0);
03378       for(int row = upperLeftCorner.getRow();
03379           row < lowerRightCorner.getRow();
03380           ++row) {
03381         typename Array2D<Type>::const_iterator rowBegin = array0.rowBegin(row);
03382         result += std::accumulate(
03383           rowBegin + upperLeftCorner.getColumn(),
03384           rowBegin + lowerRightCorner.getColumn(),
03385           static_cast<Type2>(0));
03386       }
03387       return result;
03388     }
03389 
03390     
03391     // This function computes the standard deviation of a group of
03392     // scalar samples.
03393     template <class Type>
03394     inline double
03395     variance(const Array1D<Type>& array0)
03396     {
03397       return variance(array0, type_tag<double>());
03398     }
03399 
03400     // This function computes the standard deviation, of the elements of
03401     // its argument, and allows the user to specify the precision with
03402     // which the computation is carried out.
03403     template <class Type0, class Type1>
03404     inline Type1
03405     variance(const Array1D<Type0>& array0, type_tag<Type1>)
03406     {
03407       Type1 meanValue = mean(array0, type_tag<Type1>());
03408       Type1 accumulator = 0;
03409       for(size_t index0 = 0; index0 < array0.size(); ++index0) {
03410         Type1 offset = static_cast<Type1>(array0[index0]) - meanValue;
03411         accumulator += offset * offset;
03412       }
03413       return accumulator / static_cast<Type1>(array0.size());
03414     }
03415 
03416     // This function returns an Array1D of the specified size and type
03417     // in which the value of every element is zero.
03418     template <class Type>
03419     inline Array1D<Type>
03420     zeros(size_t size, type_tag<Type>)
03421     {
03422       Array1D<Type> result(size);
03423       result = 0;
03424       return result;
03425     }
03426 
03427     // This function returns an Array2D of the specified size and type
03428     // in which the value of every element is zero.
03429     template <class Type>
03430     inline Array2D<Type>
03431     zeros(size_t rows, size_t columns, type_tag<Type>)
03432     {
03433       Array2D<Type> result(rows, columns);
03434       result = 0;
03435       return result;
03436     }
03437 
03438 
03439     // This function returns an Array3D of the specified size and type
03440     // in which the value of every element is zero.
03441     template <class Type>
03442     inline Array3D<Type>
03443     zeros(size_t shape0, size_t shape1, size_t shape2, type_tag<Type>)
03444     {
03445       Array3D<Type> result(shape0, shape1, shape2);
03446       result = 0;
03447       return result;
03448     }
03449   
03450   } // namespace numeric
03451 
03452 } // namespace dlr
03453 
03454 #endif /* #ifndef _DLR_NUMERIC_UTILITIES_H_ */

Generated on Mon Jul 9 20:34:03 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2