00001
00015 #ifndef _DLR_NUMERIC_UTILITIES_H_
00016 #define _DLR_NUMERIC_UTILITIES_H_
00017
00018 #include <cmath>
00019
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 }
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
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
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
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
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
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
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 }
01850
01851 }
01852
01853
01854
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 }
01905
01906
01907
01908
01909 #include <cmath>
01910 #include <sstream>
01911 #include <numeric>
01912
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
01967
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
02003
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
02041
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
02069
02070
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
02082
02083
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
02096
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
02113
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
02130
02131 template <class Type>
02132 inline bool
02133 anyFalse(const Array1D<Type>& array0)
02134 {
02135 return !allTrue(array0);
02136 }
02137
02138
02139
02140
02141 template <class Type>
02142 inline bool
02143 anyTrue(const Array1D<Type>& array0)
02144 {
02145 return !allFalse(array0);
02146 }
02147
02148
02149
02150
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
02159
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
02171
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
02181
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
02193
02194
02195
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
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
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
02246
02247
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
02295
02296
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
02306
02307
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
02355
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
02365
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
02375
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
02419
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
02435
02436
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
02447
02448
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
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
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
02499
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
02508
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
02517
02518
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
02527
02528
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
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
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
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
02575
02576
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
02591
02592 template <class Type>
02593 Array1D<Type>
02594 ln(const Array1D<Type>& array0)
02595 {
02596 Array1D<Type> result(array0.size());
02597
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
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633 template <class Type>
02634 Array2D<Type>
02635 ln(const Array2D<Type>& array0)
02636 {
02637 Array2D<Type> result(array0.size());
02638
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
02647
02648
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
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
02671 inline double
02672 magnitude(const Vector2D& vector0) {
02673 return std::sqrt(magnitudeSquared(vector0));
02674 }
02675
02676
02677
02678 inline double
02679 magnitude(const Vector3D& vector0) {
02680 return std::sqrt(magnitudeSquared(vector0));
02681 }
02682
02683
02684
02685
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
02697
02698 inline double
02699 magnitudeSquared(const Vector2D& vector0) {
02700 return (vector0.x() * vector0.x() + vector0.y() * vector0.y());
02701 }
02702
02703
02704
02705
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
02714
02715
02716
02717
02718
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
02728
02729
02730
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
02756
02757
02758
02759
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
02770
02771
02772
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
02793
02794
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
02804
02805
02806
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
02837
02838 template <class Type>
02839 inline Type
02840 maximum(const Array1D<Type>& array0)
02841 {
02842 return maximum(array0, std::less<Type>());
02843 }
02844
02845
02846
02847
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
02861
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
02878
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
02895
02896
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
02906
02907
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
02916 if(sampleArray.size() == 0) {
02917 meanArray.reinit(0);
02918 covarianceArray.reinit(0, 0);
02919 return;
02920 }
02921
02922
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
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
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
02962 meanArray[columnIndex] += *sampleIterator;
02963
02964
02965
02966 typename Array2D<Type>::const_iterator sampleIterator2 =
02967 sampleIterator;
02968 for(size_t covarianceIndex = columnIndex;
02969 covarianceIndex < dimensionality;
02970 ++covarianceIndex) {
02971
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
02984 meanArray[rowIndex] += *sampleIterator;
02985
02986
02987
02988 typename Array2D<Type>::const_iterator sampleIterator2 =
02989 sampleIterator;
02990 for(size_t covarianceIndex = rowIndex;
02991 covarianceIndex < dimensionality;
02992 ++covarianceIndex) {
02993
02994 covarianceArray(rowIndex, covarianceIndex) +=
02995 *sampleIterator * *sampleIterator2;
02996 sampleIterator2 += numberOfSamples;
02997 }
02998 ++sampleIterator;
02999 }
03000 }
03001 }
03002
03003
03004 meanArray /= static_cast<double>(numberOfSamples);
03005
03006
03007 for(size_t index0 = 0; index0 < dimensionality; ++index0) {
03008 for(size_t index1 = index0; index1 < dimensionality; ++index1) {
03009
03010 covarianceArray(index0, index1) -=
03011 numberOfSamples * meanArray[index0] * meanArray[index1];
03012 covarianceArray(index0, index1) /= (numberOfSamples - 1);
03013
03014
03015 if(index0 != index1) {
03016 covarianceArray(index1, index0) = covarianceArray(index0, index1);
03017 }
03018 }
03019 }
03020
03021 }
03022
03023
03024
03025
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
03038
03039
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
03049
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;
03069 }
03070
03071
03072
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
03081
03082
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
03103
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
03114
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
03125
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
03135
03136
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
03155
03156
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
03185
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
03197
03198
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
03212
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
03226
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
03235
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
03245
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
03256
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
03284
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
03296 if(!valid) {
03297 ss = 1.0;
03298 }
03299 } else {
03300 valid = true;
03301 }
03302 Type rt = std::sqrt(ss);
03303
03304
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
03315
03316 template <class Type>
03317 inline double
03318 standardDeviation(const Array1D<Type>& array0)
03319 {
03320 return standardDeviation(array0, type_tag<double>());
03321 }
03322
03323
03324
03325
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
03334
03335
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
03344
03345
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
03356
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
03369
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
03392
03393 template <class Type>
03394 inline double
03395 variance(const Array1D<Type>& array0)
03396 {
03397 return variance(array0, type_tag<double>());
03398 }
03399
03400
03401
03402
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
03417
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
03428
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
03440
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 }
03451
03452 }
03453
03454 #endif