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
00159 template <class IterType>
00160 inline size_t
00161 argmax(IterType beginIter, IterType endIter);
00162
00163
00185 template <class Type, class Functor>
00186 inline size_t
00187 argmax(const Array1D<Type>& array0, Functor comparator);
00188
00189
00214 template <class IterType, class Functor>
00215 inline size_t
00216 argmax(IterType beginIter, IterType endIter, Functor comparator);
00217
00218
00228 template <class Type>
00229 inline Index2D
00230 argmax2D(const Array2D<Type>& array0);
00231
00232
00251 template <class Type, class Functor>
00252 inline Index2D
00253 argmax2D(const Array2D<Type>& array0, Functor comparator);
00254
00255
00266 template <class Type>
00267 inline size_t
00268 argmin(const Array1D<Type>& array0);
00269
00270
00288 template <class Type, class Functor>
00289 inline size_t
00290 argmin(const Array1D<Type>& array0, Functor comparator);
00291
00292
00302 template <class Type>
00303 inline Index2D
00304 argmin2D(const Array2D<Type>& array0);
00305
00306
00321 template <class Type, class Functor>
00322 inline Index2D
00323 argmin2D(const Array2D<Type>& array0, Functor comparator);
00324
00325
00337 template <class Type>
00338 Array1D<size_t>
00339 argsort(const Array1D<Type>& array0);
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00371 template <class Type>
00372 Array1D<Type>
00373 axisMax(const Array2D<Type>& array0,
00374 size_t axis) {return axisMaximum(array0, axis);}
00375
00392 template <class Type>
00393 inline Array1D<Type>
00394 axisMaximum(const Array2D<Type>& array0, size_t axis);
00395
00426 template <class Type, class Functor>
00427 Array1D<Type>
00428 axisMaximum(const Array2D<Type>& array0, size_t axis, Functor comparator);
00429
00439 template <class Type>
00440 inline Array1D<Type>
00441 axisMin(const Array2D<Type>& array0,
00442 size_t axis) {return axisMinimum(array0, axis);}
00443
00460 template <class Type>
00461 inline Array1D<Type>
00462 axisMinimum(const Array2D<Type>& array0, size_t axis);
00463
00494 template <class Type, class Functor>
00495 Array1D<Type>
00496 axisMinimum(const Array2D<Type>& array0, size_t axis, Functor comparator);
00497
00522 template <class Type>
00523 inline Array1D<typename NumericTraits<Type>::SumType>
00524 axisSum(const Array2D<Type>& array0, size_t axis);
00525
00548 template <class Type, class ResultType>
00549 inline Array1D<ResultType>
00550 axisSum(const Array2D<Type>& array0, size_t axis,
00551 type_tag<ResultType> resultTag);
00552
00592 template <class Type, class ResultType, class Functor>
00593 Array1D<ResultType>
00594 axisSum(const Array2D<Type>& array0, size_t axis,
00595 type_tag<ResultType> resultTag,
00596 const ResultType& initialValue, Functor adder);
00597
00625 template <class Type>
00626 Array2D<Type>
00627 columnIndices(size_t rows, size_t columns, type_tag<Type> typeTag);
00628
00660 template <class Type0, class Type1>
00661 inline Array1D<Type1>
00662 compress(const Array1D<Type0>& condition, const Array1D<Type1>& input);
00663
00690 template <class Type0, class Type1>
00691 Array1D<Type1>
00692 compress(const Array1D<Type0>& condition, const Array1D<Type1>& input,
00693 size_t numTrue);
00694
00695
00706 template <class Type>
00707 inline size_t
00708 count(const Array1D<Type>& array0);
00709
00723 inline Vector3D
00724 cross(const Vector3D& vector0, const Vector3D& vector1);
00725
00737 template <class Type>
00738 inline typename NumericTraits<Type>::ProductType
00739 dot(const Array1D<Type>& array0, const Array1D<Type>& array1);
00740
00755 template <class Type0, class Type1, class Type2>
00756 inline Type2
00757 dot(const Array1D<Type0>& array0, const Array1D<Type1>& array1,
00758 type_tag<Type2> typeTag);
00759
00769 inline double
00770 dot(const Vector2D& vector0, const Vector2D& vector1);
00771
00781 inline double
00782 dot(const Vector3D& vector0, const Vector3D& vector1);
00783
00805 template <class Type>
00806 Array2D<Type>
00807 equivalentMatrix(const Array1D<Type>& vector0, size_t rowsInMatrix);
00808
00809
00832 template <class Type>
00833 void
00834 getMeanAndCovariance(const Array2D<Type>& sampleArray,
00835 Array1D<double>& mean,
00836 Array2D<double>& covariance,
00837 size_t majorAxis=0);
00838
00839
00857 template <class Type>
00858 Array2D<Type>
00859 identity(size_t rows, size_t columns, type_tag<Type> typeTag);
00860
00861
00871 template <class Type>
00872 Array1D<Type>
00873 ln(const Array1D<Type>& array0);
00874
00875
00885 template <class Type>
00886 Array2D<Type>
00887 ln(const Array2D<Type>& array0);
00888
00889
00910 template <class Type>
00911 Array2D<Type>
00912 logicalNot(const Array2D<Type>& array0);
00913
00923 template <class Type>
00924 inline Type
00925 magnitude(const Array1D<Type>& array0);
00926
00936 inline double
00937 magnitude(const Vector2D& vector0);
00938
00948 inline double
00949 magnitude(const Vector3D& vector0);
00950
00951
00962 template <class Type>
00963 inline typename NumericTraits<Type>::ProductType
00964 magnitudeSquared(const Array1D<Type>& array0);
00965
00966
00977 inline double
00978 magnitudeSquared(const Vector2D& vector0);
00979
00980
00991 inline double
00992 magnitudeSquared(const Vector3D& vector0);
00993
00994
01012 template <class Type>
01013 inline Array1D<typename NumericTraits<Type>::ProductType>
01014 matrixMultiply(const Array1D<Type>& vector0, const Array2D<Type>& matrix0);
01015
01033 template <class Type0, class Type1, class Type2>
01034 Array1D<Type2>
01035 matrixMultiply(const Array1D<Type0>& vector0, const Array2D<Type0>& matrix0,
01036 type_tag<Type2> typeTag);
01037
01054 template <class Type>
01055 inline Array1D<typename NumericTraits<Type>::ProductType>
01056 matrixMultiply(const Array2D<Type>& matrix0, const Array1D<Type>& vector0);
01057
01075 template <class Type0, class Type1, class Type2>
01076 Array1D<Type2>
01077 matrixMultiply(const Array2D<Type0>& matrix0, const Array1D<Type1>& vector0,
01078 type_tag<Type2> typeTag);
01079
01080
01095 template <class Type>
01096 inline Array2D<typename NumericTraits<Type>::ProductType>
01097 matrixMultiply(const Array2D<Type>& matrix0, const Array2D<Type>& matrix1);
01098
01116 template <class Type0, class Type1, class Type2>
01117 Array2D<Type2>
01118 matrixMultiply(const Array2D<Type0>& matrix0, const Array2D<Type1>& matrix1,
01119 type_tag<Type2> typeTag);
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01149 template <class Type>
01150 inline Type
01151 maximum(const Array1D<Type>& array0);
01152
01172 template <class Type, class Functor>
01173 Type
01174 maximum(const Array1D<Type>& array0, Functor comparator);
01175
01176
01188 template <class Iterator, class Type>
01189 Type
01190 mean(const Iterator& beginIter, const Iterator& endIter);
01191
01192
01204 template <class Type>
01205 inline double
01206 mean(const Array1D<Type>& array0);
01207
01208
01225 template <class Type0, class Type1>
01226 inline Type1
01227 mean(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01257 template <class Type>
01258 inline Type
01259 minimum(const Array1D<Type>& array0);
01260
01280 template <class Type, class Functor>
01281 Type
01282 minimum(const Array1D<Type>& array0, Functor comparator);
01283
01284
01312 template <class FUNCTOR>
01313 double newtonRaphson(double startPoint, FUNCTOR objectiveFunction,
01314 double epsilon, size_t maxIterations);
01315
01337 template <class Type>
01338 inline double
01339 normalizedCorrelation(const Array1D<Type>& signal0,
01340 const Array1D<Type>& signal1);
01341
01342
01360 template <class Type, class Type2>
01361 Type2
01362 normalizedCorrelation(const Array1D<Type>& signal0,
01363 const Array1D<Type>& signal1,
01364 type_tag<Type2> typeTag);
01365
01378 template <class Type>
01379 inline Array1D<Type>
01380 ones(int size, type_tag<Type> typeTag);
01381
01397 template <class Type>
01398 inline Array2D<Type>
01399 ones(int rows, int columns, type_tag<Type> typeTag);
01400
01416 template <class Type>
01417 inline Array2D<typename NumericTraits<Type>::ProductType>
01418 outerProduct(const Array1D<Type>& array0, const Array1D<Type>& array1);
01419
01439 template <class Type0, class Type1, class Type2>
01440 Array2D<Type2>
01441 outerProduct(const Array1D<Type0>& array0, const Array1D<Type1>& array1,
01442 type_tag<Type2> typeTag);
01443
01483 template <class Type>
01484 Array1D<Type>
01485 range(Type start, Type stop, Type stride=1);
01486
01502 template <class Type>
01503 inline Array1D<Type>
01504 ravel(Array2D<Type>& inputArray) {return inputArray.ravel();}
01505
01517 template <class Type>
01518 inline const Array1D<Type>
01519 ravel(const Array2D<Type>& inputArray) {return inputArray.ravel();}
01520
01521
01533 template <class Type>
01534 inline Type
01535 rms(const Array1D<Type>& array0);
01536
01537
01554 template <class Type0, class Type1>
01555 Type1
01556 rms(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01557
01558
01585 template <class Type>
01586 Array2D<Type>
01587 rowIndices(size_t rows, size_t columns, type_tag<Type> typeTag);
01588
01589
01604 template <class Type0, class Type1>
01605 inline bool
01606 shapeMatch(const Array1D<Type0>& array0, const Array1D<Type1>& array1);
01607
01608
01623 template <class Type0, class Type1>
01624 inline bool
01625 shapeMatch(const Array2D<Type0>& array0, const Array2D<Type1>& array1);
01626
01627
01642 template <class Type0, class Type1>
01643 inline bool
01644 shapeMatch(const Array3D<Type0>& array0, const Array3D<Type1>& array1);
01645
01646
01655 template <class Type>
01656 inline Array2D<Type>
01657 skewSymmetric(const Array1D<Type>& vector0);
01658
01659
01718 template <class Type>
01719 void
01720 solveQuadratic(Type c0, Type c1, Type c2,
01721 Type& root0, Type& root1, bool& valid,
01722 bool checkValidity=true);
01723
01724
01742 template <class Type>
01743 inline double
01744 standardDeviation(const Array1D<Type>& array0);
01745
01769 template <class Type0, class Type1>
01770 inline Type1
01771 standardDeviation(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01772
01773
01783 template <class Type>
01784 inline typename NumericTraits<Type>::SumType
01785 sum(const Array1D<Type>& array0);
01786
01787
01801 template <class Type, class Type2>
01802 Type2
01803 sum(const Array1D<Type>& array0, type_tag<Type2> typeTag);
01804
01805
01826 template <class Type>
01827 inline typename NumericTraits<Type>::SumType
01828 sum(const Array2D<Type>& array0,
01829 const Index2D& upperLeftCorner,
01830 const Index2D& lowerRightCorner);
01831
01832
01857 template <class Type, class Type2>
01858 Type2
01859 sum(const Array2D<Type>& array0,
01860 const Index2D& upperLeftCorner,
01861 const Index2D& lowerRightCorner,
01862 type_tag<Type2> typeTag);
01863
01864
01882 template <class Type>
01883 inline double
01884 variance(const Array1D<Type>& array0);
01885
01908 template <class Type0, class Type1>
01909 inline Type1
01910 variance(const Array1D<Type0>& array0, type_tag<Type1> typeTag);
01911
01924 template <class Type>
01925 inline Array1D<Type>
01926 zeros(size_t size, type_tag<Type> typeTag);
01927
01943 template <class Type>
01944 inline Array2D<Type>
01945 zeros(size_t rows, size_t columns, type_tag<Type> typeTag);
01946
01965 template <class Type>
01966 inline Array3D<Type>
01967 zeros(size_t shape0, size_t shape1, size_t shape2, type_tag<Type> typeTag);
01968
01969 }
01970
01971 }
01972
01973
01974
01975
01976 namespace dlr {
01977
01978 using numeric::abs;
01979 using numeric::abs;
01980 using numeric::allFalse;
01981 using numeric::allTrue;
01982 using numeric::anyFalse;
01983 using numeric::anyTrue;
01984 using numeric::argmax;
01985 using numeric::argmin;
01986 using numeric::argsort;
01987 using numeric::axisMax;
01988 using numeric::axisMaximum;
01989 using numeric::axisMin;
01990 using numeric::axisMinimum;
01991 using numeric::axisSum;
01992 using numeric::columnIndices;
01993 using numeric::compress;
01994 using numeric::count;
01995 using numeric::cross;
01996 using numeric::dot;
01997 using numeric::equivalentMatrix;
01998 using numeric::getMeanAndCovariance;
01999 using numeric::identity;
02000 using numeric::ln;
02001 using numeric::logicalNot;
02002 using numeric::magnitude;
02003 using numeric::magnitudeSquared;
02004 using numeric::matrixMultiply;
02005 using numeric::maximum;
02006 using numeric::mean;
02007 using numeric::minimum;
02008 using numeric::newtonRaphson;
02009 using numeric::normalizedCorrelation;
02010 using numeric::ones;
02011 using numeric::outerProduct;
02012 using numeric::range;
02013 using numeric::ravel;
02014 using numeric::rms;
02015 using numeric::rowIndices;
02016 using numeric::shapeMatch;
02017 using numeric::skewSymmetric;
02018 using numeric::solveQuadratic;
02019 using numeric::standardDeviation;
02020 using numeric::sum;
02021 using numeric::variance;
02022 using numeric::zeros;
02023
02024 }
02025
02026
02027
02028
02029 #include <cmath>
02030 #include <sstream>
02031 #include <numeric>
02032
02033
02034 namespace dlr {
02035
02036 namespace numeric {
02037
02049 namespace privateCode {
02050
02056 template <class Type>
02057 struct absFunctor : public std::unary_function<Type, Type> {
02065 inline Type operator()(const Type& input) {
02066 DLR_THROW3(NotImplementedException,
02067 "absFunctor<Type>::operator()(const Type&)",
02068 "absFunctor must be specialized for each type.");
02069 return static_cast<Type>(0);
02070 }
02071 };
02072
02076 template <>
02077 struct absFunctor<long double>
02078 : public std::unary_function<long double, long double> {
02085 inline double operator()(const long double& input) {
02086
02087
02088 return (input > 0.0) ? input : -input;
02089 }
02090 };
02091
02092
02096 template <>
02097 struct absFunctor<double> : public std::unary_function<double, double> {
02104 inline double operator()(const double& input) {
02105 return std::fabs(input);
02106 }
02107 };
02108
02109
02113 template <>
02114 struct absFunctor<float> : public std::unary_function<float, float> {
02121 inline float operator()(const float& input) {
02122
02123
02124 return fabsf(input);
02125 }
02126 };
02127
02128
02132 template <>
02133 struct absFunctor<long int>
02134 : public std::unary_function<long int, long int> {
02141 inline long int operator()(const long int& input) {
02142 return std::labs(input);
02143 }
02144 };
02145
02146
02150 template <>
02151 struct absFunctor<long long int>
02152 : public std::unary_function<long long int, long long int> {
02159 inline long long int operator()(const long long int& input) {
02160
02161
02162 return input >= 0LL ? input : -input;
02163 }
02164 };
02165
02166
02170 template <>
02171 struct absFunctor<int> : public std::unary_function<int, int> {
02178 inline int operator()(const int& input) {
02179 return std::abs(input);
02180 }
02181 };
02182
02183
02184 }
02188
02189
02190
02191 template <class Type>
02192 Array1D<Type>
02193 abs(const Array1D<Type>& array0)
02194 {
02195 Array1D<Type> result(array0.size());
02196 std::transform(array0.begin(), array0.end(), result.begin(),
02197 privateCode::absFunctor<Type>());
02198 return result;
02199 }
02200
02201
02202
02203
02204 template <class Type>
02205 Array2D<Type>
02206 abs(const Array2D<Type>& array0)
02207 {
02208 Array2D<Type> result(array0.rows(), array0.columns());
02209 std::transform(array0.begin(), array0.end(), result.begin(),
02210 privateCode::absFunctor<Type>());
02211 return result;
02212 }
02213
02214
02215
02216
02217 template <class Type>
02218 bool
02219 allFalse(const Array1D<Type>& array0)
02220 {
02221 for(typename Array1D<Type>::const_iterator iter = array0.begin();
02222 iter != array0.end();
02223 ++iter) {
02224 if(*iter) {
02225 return false;
02226 }
02227 }
02228 return true;
02229 }
02230
02231
02232
02233
02234 template <class Type>
02235 bool
02236 allTrue(const Array1D<Type>& array0)
02237 {
02238 for(typename Array1D<Type>::const_iterator iter = array0.begin();
02239 iter != array0.end();
02240 ++iter) {
02241 if(!(*iter)) {
02242 return false;
02243 }
02244 }
02245 return true;
02246 }
02247
02248
02249
02250
02251 template <class Type>
02252 inline bool
02253 anyFalse(const Array1D<Type>& array0)
02254 {
02255 return !allTrue(array0);
02256 }
02257
02258
02259
02260
02261 template <class Type>
02262 inline bool
02263 anyTrue(const Array1D<Type>& array0)
02264 {
02265 return !allFalse(array0);
02266 }
02267
02268
02269
02270
02271 template <class Type>
02272 inline size_t
02273 argmax(const Array1D<Type>& array0)
02274 {
02275 return argmax(array0, std::less<Type>());
02276 }
02277
02278
02279
02280
02281 template <class IterType>
02282 inline size_t
02283 argmax(IterType beginIter, IterType endIter)
02284 {
02285 return argmax(beginIter, endIter, std::less<IterType>());
02286 }
02287
02288
02289
02290
02291 template <class Type, class Functor>
02292 inline size_t
02293 argmax(const Array1D<Type>& array0, Functor comparator)
02294 {
02295 return argmax(array0.begin(), array0.end(), comparator);
02296 }
02297
02298
02299
02300
02301 template <class IterType, class Functor>
02302 inline size_t
02303 argmax(IterType beginIter, IterType endIter, Functor comparator)
02304 {
02305 return static_cast<size_t>(
02306 std::max_element(beginIter, endIter, comparator) - beginIter);
02307 }
02308
02309
02310
02311
02312 template <class Type>
02313 inline Index2D
02314 argmax2D(const Array2D<Type>& array0)
02315 {
02316 return argmax2D(array0, std::less<Type>());
02317 }
02318
02319
02320
02321
02322
02323 template <class Type, class Functor>
02324 inline Index2D
02325 argmax2D(const Array2D<Type>& array0, Functor comparator)
02326 {
02327 size_t ravelIndex = argmax(array0.ravel(), comparator);
02328 size_t row = ravelIndex / array0.columns();
02329 size_t column = ravelIndex - row * array0.columns();
02330 return Index2D(row, column);
02331 }
02332
02333
02334
02335
02336 template <class Type>
02337 inline size_t
02338 argmin(const Array1D<Type>& array0)
02339 {
02340 return argmin(array0, std::less<Type>());
02341 }
02342
02343
02344
02345
02346 template <class Type, class Functor>
02347 inline size_t
02348 argmin(const Array1D<Type>& array0, Functor comparator)
02349 {
02350 const Type* minPtr = std::min_element(array0.begin(), array0.end(),
02351 comparator);
02352 return static_cast<size_t>(minPtr - array0.begin());
02353 }
02354
02355
02356
02357
02358 template <class Type>
02359 inline Index2D
02360 argmin2D(const Array2D<Type>& array0)
02361 {
02362 return argmin2D(array0, std::less<Type>());
02363 }
02364
02365
02366
02367
02368
02369 template <class Type, class Functor>
02370 inline Index2D
02371 argmin2D(const Array2D<Type>& array0, Functor comparator)
02372 {
02373 size_t ravelIndex = argmin(array0.ravel(), comparator);
02374 size_t row = ravelIndex / array0.columns();
02375 size_t column = ravelIndex - row * array0.columns();
02376 return Index2D(row, column);
02377 }
02378
02379
02380
02381
02382
02383
02384 template <class Type>
02385 Array1D<size_t>
02386 argsort(const Array1D<Type>& array0)
02387 {
02388 Array1D< std::pair<Type, size_t> > sortVector(array0.size());
02389 Array1D<size_t> resultVector(array0.size());
02390
02391 for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02392 sortVector[index0] = std::pair<Type, size_t>(array0[index0], index0);
02393 }
02394 std::sort(sortVector.begin(), sortVector.end());
02395 std::transform(sortVector.begin(), sortVector.end(), resultVector.begin(),
02396 ExtractSecondFunctor<Type, size_t>());
02397 return resultVector;
02398 }
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425 template <class Type>
02426 inline Array1D<Type>
02427 axisMaximum(const Array2D<Type>& array0, size_t axis)
02428 {
02429 return axisMaximum(array0, axis, std::less<Type>());
02430 }
02431
02432
02433
02434
02435
02436 template <class Type, class Functor>
02437 Array1D<Type>
02438 axisMaximum(const Array2D<Type>& array0, size_t axis, Functor comparator)
02439 {
02440 Array1D<Type> result;
02441 switch(axis) {
02442 case 0:
02443 result.reinit(array0.columns());
02444 for(size_t column = 0; column < array0.columns(); ++column) {
02445 const Type* dataPtr = array0.data(0, column);
02446 Type columnMax = *dataPtr;
02447 size_t stride = array0.columns();
02448 for(size_t row = 0; row < array0.rows(); ++row) {
02449 if(!comparator(*dataPtr, columnMax)) {
02450 columnMax = *dataPtr;
02451 }
02452 dataPtr += stride;
02453 }
02454 result(column) = columnMax;
02455 }
02456 break;
02457 case 1:
02458 result.reinit(array0.rows());
02459 for(size_t row = 0; row < array0.rows(); ++row) {
02460 const Type* dataPtr = array0.data(row, 0);
02461 Type rowMax = *dataPtr;
02462 for(size_t column = 0; column < array0.columns(); ++column) {
02463 if(!comparator(*dataPtr, rowMax)) {
02464 rowMax = *dataPtr;
02465 }
02466 ++dataPtr;
02467 }
02468 result(row) = rowMax;
02469 }
02470 break;
02471 default:
02472 std::ostringstream message;
02473 message << "Axis " << axis << " is invalid for an Array2D.";
02474 DLR_THROW3(IndexException, "axisMaximum(const Array2D&, size_t, ...)",
02475 message.str().c_str());
02476 break;
02477 }
02478 return result;
02479 }
02480
02481
02482
02483
02484
02485 template <class Type>
02486 inline Array1D<Type>
02487 axisMinimum(const Array2D<Type>& array0, size_t axis)
02488 {
02489 return axisMinimum(array0, axis, std::less<Type>());
02490 }
02491
02492
02493
02494
02495
02496 template <class Type, class Functor>
02497 Array1D<Type>
02498 axisMinimum(const Array2D<Type>& array0, size_t axis, Functor comparator)
02499 {
02500 Array1D<Type> result;
02501 switch(axis) {
02502 case 0:
02503 result.reinit(array0.columns());
02504 for(size_t column = 0; column < array0.columns(); ++column) {
02505 const Type* dataPtr = array0.data(0, column);
02506 Type columnMax = *dataPtr;
02507 size_t stride = array0.columns();
02508 for(size_t row = 0; row < array0.rows(); ++row) {
02509 if(comparator(*dataPtr, columnMax)) {
02510 columnMax = *dataPtr;
02511 }
02512 dataPtr += stride;
02513 }
02514 result(column) = columnMax;
02515 }
02516 break;
02517 case 1:
02518 result.reinit(array0.rows());
02519 for(size_t row = 0; row < array0.rows(); ++row) {
02520 const Type* dataPtr = array0.data(row, 0);
02521 Type rowMax = *dataPtr;
02522 for(size_t column = 0; column < array0.columns(); ++column) {
02523 if(comparator(*dataPtr, rowMax)) {
02524 rowMax = *dataPtr;
02525 }
02526 ++dataPtr;
02527 }
02528 result(row) = rowMax;
02529 }
02530 break;
02531 default:
02532 std::ostringstream message;
02533 message << "Axis " << axis << " is invalid for an Array2D.";
02534 DLR_THROW3(IndexException, "axisMinimum(const Array2D&, size_t, ...)",
02535 message.str().c_str());
02536 break;
02537 }
02538 return result;
02539 }
02540
02541
02542
02543
02544 template <class Type>
02545 inline Array1D<typename NumericTraits<Type>::SumType>
02546 axisSum(const Array2D<Type>& array0, size_t axis)
02547 {
02548 return axisSum(array0, axis,
02549 type_tag<typename NumericTraits<Type>::SumType>());
02550 }
02551
02552
02553
02554 template <class Type, class ResultType>
02555 inline Array1D<ResultType>
02556 axisSum(const Array2D<Type>& array0, size_t axis, type_tag<ResultType>)
02557 {
02558 return axisSum(array0, axis, type_tag<ResultType>(),
02559 static_cast<ResultType>(0), std::plus<ResultType>());
02560 }
02561
02562
02563
02564 template <class Type, class ResultType, class Functor>
02565 Array1D<ResultType>
02566 axisSum(const Array2D<Type>& array0, size_t axis, type_tag<ResultType>,
02567 const ResultType& initialValue, Functor adder)
02568 {
02569 Array1D<ResultType> result;
02570 switch(axis) {
02571 case 0:
02572 result.reinit(array0.columns());
02573 for(size_t column = 0; column < array0.columns(); ++column) {
02574 ResultType columnSum = initialValue;
02575 const Type* dataPtr = array0.data(0, column);
02576 size_t stride = array0.columns();
02577 for(size_t row = 0; row < array0.rows(); ++row) {
02578 columnSum = adder(columnSum, *dataPtr);
02579 dataPtr += stride;
02580 }
02581 result(column) = columnSum;
02582 }
02583 break;
02584 case 1:
02585 result.reinit(array0.rows());
02586 for(size_t row = 0; row < array0.rows(); ++row) {
02587 ResultType rowSum = initialValue;
02588 const Type* dataPtr = array0.data(row, 0);
02589 for(size_t column = 0; column < array0.columns(); ++column) {
02590 rowSum = adder(rowSum, *dataPtr);
02591 ++dataPtr;
02592 }
02593 result(row) = rowSum;
02594 }
02595 break;
02596 default:
02597 std::ostringstream message;
02598 message << "Axis " << axis << " is invalid for an Array2D.";
02599 DLR_THROW3(IndexException, "axisSum(const Array2D&, size_t, ...)",
02600 message.str().c_str());
02601 break;
02602 }
02603 return result;
02604 }
02605
02606
02607
02608 template <class Type>
02609 Array2D<Type>
02610 columnIndices(size_t rows, size_t columns, type_tag<Type>)
02611 {
02612 Array2D<Type> returnValue(rows, columns);
02613 Array1D<Type> modelRow = range(static_cast<Type>(0),
02614 static_cast<Type>(columns),
02615 static_cast<Type>(1));
02616 for(size_t row=0; row < rows; ++row) {
02617 std::copy(modelRow.begin(), modelRow.end(), returnValue.data(row, 0));
02618 }
02619 return returnValue;
02620 }
02621
02622
02623
02624
02625 template <class Type0, class Type1>
02626 inline Array1D<Type1>
02627 compress(const Array1D<Type0>& condition,
02628 const Array1D<Type1>& input)
02629 {
02630 size_t numTrue = count(condition);
02631 return compress(condition, input, numTrue);
02632 }
02633
02634
02635
02636
02637 template <class Type0, class Type1>
02638 Array1D<Type1>
02639 compress(const Array1D<Type0>& condition,
02640 const Array1D<Type1>& input,
02641 size_t numTrue)
02642 {
02643 if(condition.size() != input.size()) {
02644 std::ostringstream message;
02645 message << "Condition and input arguments must have the same "
02646 << "size, but condition has size = " << condition.size()
02647 << ", while input has size = " << input.size() << ".";
02648 DLR_THROW3(ValueException,
02649 "compress(const Array1D&, const Array1D&, size_t)",
02650 message.str().c_str());
02651 }
02652 Array1D<Type1> result(numTrue);
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671 typename Array1D<Type1>::const_iterator first = input.begin();
02672 typename Array1D<Type1>::const_iterator last = input.end();
02673 typename Array1D<Type0>::const_iterator mask = condition.begin();
02674 typename Array1D<Type1>::iterator target = result.begin();
02675 while(first != last) {
02676 if(*mask) {
02677 *(target++) = *first;
02678 }
02679 ++mask;
02680 ++first;
02681 }
02682
02683 return result;
02684 }
02685
02686
02687
02688 template <class Type>
02689 inline size_t
02690 count(const Array1D<Type>& x)
02691 {
02692 return std::count_if(x.begin(), x.end(), StaticCastFunctor<Type, bool>());
02693 }
02694
02695
02696
02697 inline Vector3D
02698 cross(const Vector3D& vector0, const Vector3D& vector1) {
02699 return Vector3D((vector0.y() * vector1.z()) - (vector0.z() * vector1.y()),
02700 (vector0.z() * vector1.x()) - (vector0.x() * vector1.z()),
02701 (vector0.x() * vector1.y()) - (vector0.y() * vector1.x()));
02702 }
02703
02704
02705
02706
02707 template <class Type>
02708 inline typename NumericTraits<Type>::ProductType
02709 dot(const Array1D<Type>& x, const Array1D<Type>& y)
02710 {
02711 return dot(x, y, type_tag<typename NumericTraits<Type>::ProductType>());
02712 }
02713
02714
02715
02716
02717 template <class Type0, class Type1, class Type2>
02718 inline Type2
02719 dot(const Array1D<Type0>& x, const Array1D<Type1>& y, type_tag<Type2>)
02720 {
02721 if(x.size() != y.size()) {
02722 std::ostringstream message;
02723 message << "Input arguments must have matching sizes, but x.size() == "
02724 << x.size() << " and y.size() == " << y.size() << "."
02725 << std::endl;
02726 DLR_THROW3(ValueException, "dot()", message.str().c_str());
02727 }
02728 return std::inner_product(x.begin(), x.end(), y.begin(),
02729 static_cast<Type2>(0));
02730 }
02731
02732
02733 inline double
02734 dot(const Vector2D& vector0, const Vector2D& vector1)
02735 {
02736 return vector0.x() * vector1.x() + vector0.y() * vector1.y();
02737 }
02738
02739
02740 inline double
02741 dot(const Vector3D& vector0, const Vector3D& vector1)
02742 {
02743 return (vector0.x() * vector1.x() + vector0.y() * vector1.y()
02744 + vector0.z() * vector1.z());
02745 }
02746
02747
02748 template <class Type>
02749 Array2D<Type>
02750 equivalentMatrix(const Array1D<Type>& vector0, size_t rowsInMatrix)
02751 {
02752 Array2D<Type> XMatrix = zeros(rowsInMatrix, vector0.size() * rowsInMatrix,
02753 type_tag<Type>());
02754 for(size_t XRow = 0; XRow != rowsInMatrix; ++XRow) {
02755 for(size_t index0 = 0; index0 < vector0.length(); ++index0) {
02756 XMatrix(XRow, index0 * rowsInMatrix + XRow) = vector0(index0);
02757 }
02758 }
02759 return XMatrix;
02760 }
02761
02762
02763
02764
02765 template <class Type>
02766 Array2D<Type>
02767 identity(size_t rows, size_t columns, type_tag<Type>)
02768 {
02769 Array2D<Type> returnArray = zeros(rows, columns, type_tag<Type>());
02770 size_t rank = std::min(rows, columns);
02771 for(size_t index = 0; index < rank; ++index) {
02772 returnArray(index, index) = static_cast<Type>(1);
02773 }
02774 return returnArray;
02775 }
02776
02777
02778
02779
02780 template <class Type>
02781 Array1D<Type>
02782 ln(const Array1D<Type>& array0)
02783 {
02784 Array1D<Type> result(array0.size());
02785
02786 for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02787 result[index0] = std::log(array0[index0]);
02788 }
02789 return result;
02790 }
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821 template <class Type>
02822 Array2D<Type>
02823 ln(const Array2D<Type>& array0)
02824 {
02825 Array2D<Type> result(array0.size());
02826
02827 for(size_t index0 = 0; index0 < array0.size(); ++index0) {
02828 result[index0] = std::log(array0[index0]);
02829 }
02830 return result;
02831 }
02832
02833
02834
02835
02836
02837 template <class Type>
02838 Array2D<Type>
02839 logicalNot(const Array2D<Type>& array0)
02840 {
02841 Array2D<Type> result(array0.rows(), array0.columns());
02842 std::transform(array0.begin(), array0.end(), result.begin(),
02843 unaryComposeFunctor(StaticCastFunctor<bool, Type>(),
02844 std::logical_not<Type>()));
02845 return result;
02846 }
02847
02848
02849
02850 template <class Type>
02851 inline Type
02852 magnitude(const Array1D<Type>& array0)
02853 {
02854 return static_cast<Type>(std::sqrt(magnitudeSquared(array0)));
02855 }
02856
02857
02858
02859 inline double
02860 magnitude(const Vector2D& vector0) {
02861 return std::sqrt(magnitudeSquared(vector0));
02862 }
02863
02864
02865
02866 inline double
02867 magnitude(const Vector3D& vector0) {
02868 return std::sqrt(magnitudeSquared(vector0));
02869 }
02870
02871
02872
02873
02874 template <class Type>
02875 inline typename NumericTraits<Type>::ProductType
02876 magnitudeSquared(const Array1D<Type>& array0)
02877 {
02878 typedef typename NumericTraits<Type>::ProductType ProductType;
02879 return std::inner_product(array0.begin(), array0.end(),
02880 array0.begin(), static_cast<ProductType>(0));
02881 }
02882
02883
02884
02885
02886 inline double
02887 magnitudeSquared(const Vector2D& vector0) {
02888 return (vector0.x() * vector0.x() + vector0.y() * vector0.y());
02889 }
02890
02891
02892
02893
02894 inline double
02895 magnitudeSquared(const Vector3D& vector0) {
02896 return (vector0.x() * vector0.x() + vector0.y() * vector0.y()
02897 + vector0.z() * vector0.z());
02898 }
02899
02900
02901
02902
02903
02904
02905
02906
02907 template <class Type>
02908 inline Array1D<typename NumericTraits<Type>::ProductType>
02909 matrixMultiply(const Array1D<Type>& vector0, const Array2D<Type>& matrix0)
02910 {
02911 return matrixMultiply(
02912 vector0, matrix0, type_tag<typename NumericTraits<Type>::ProductType>());
02913 }
02914
02915
02916
02917
02918
02919 template <class Type0, class Type1, class Type2>
02920 Array1D<Type2>
02921 matrixMultiply(const Array1D<Type0>& vector0, const Array2D<Type0>& matrix0,
02922 type_tag<Type2>)
02923 {
02924 if(vector0.size() != matrix0.rows()) {
02925 std::ostringstream message;
02926 message << "Can't left-multiply a "
02927 << matrix0.rows() << " x " << matrix0.columns()
02928 << " matrix by a " << vector0.size() << " element vector\n";
02929 DLR_THROW(ValueException, "matrixMultiply()", message.str().c_str());
02930 }
02931 Array1D<Type2> result = zeros(matrix0.columns(), type_tag<Type2>());
02932 size_t index = 0;
02933 for(size_t row = 0; row < matrix0.rows(); ++row) {
02934 for(size_t column = 0; column < matrix0.columns(); ++column) {
02935 result[column] += (static_cast<Type2>(vector0[row])
02936 * static_cast<Type2>(matrix0[index]));
02937 ++index;
02938 }
02939 }
02940 return result;
02941 }
02942
02943
02944
02945
02946
02947
02948 template <class Type>
02949 inline Array1D<typename NumericTraits<Type>::ProductType>
02950 matrixMultiply(const Array2D<Type>& matrix0, const Array1D<Type>& vector0)
02951 {
02952 return matrixMultiply(
02953 matrix0, vector0, type_tag<typename NumericTraits<Type>::ProductType>());
02954 }
02955
02956
02957
02958
02959
02960
02961 template <class Type0, class Type1, class Type2>
02962 Array1D<Type2>
02963 matrixMultiply(const Array2D<Type0>& matrix0, const Array1D<Type1>& vector0,
02964 type_tag<Type2>)
02965 {
02966 if(vector0.size() != matrix0.columns()) {
02967 std::ostringstream message;
02968 message << "matrixMultiply() -- can't right-multiply a "
02969 << matrix0.rows() << " x " << matrix0.columns()
02970 << " matrix by a " << vector0.size() << " element vector\n";
02971 DLR_THROW(ValueException, "matrixMultiply()", message.str().c_str());
02972 }
02973 Array1D<Type2> result(matrix0.rows());
02974 for(size_t row = 0; row < matrix0.rows(); ++row) {
02975 result[row] = dot(vector0, matrix0.row(row), type_tag<Type2>());
02976 }
02977 return result;
02978 }
02979
02980
02981
02982
02983 template <class Type>
02984 inline Array2D<typename NumericTraits<Type>::ProductType>
02985 matrixMultiply(const Array2D<Type>& matrix0, const Array2D<Type>& matrix1)
02986 {
02987 return matrixMultiply(
02988 matrix0, matrix1, type_tag<typename NumericTraits<Type>::ProductType>());
02989 }
02990
02991
02992
02993
02994
02995 template <class Type0, class Type1, class Type2>
02996 Array2D<Type2>
02997 matrixMultiply(const Array2D<Type0>& matrix0, const Array2D<Type1>& matrix1,
02998 type_tag<Type2>)
02999 {
03000 if(matrix1.rows() != matrix0.columns()) {
03001 std::ostringstream message;
03002 message << "matrixMultiply() -- can't left-multiply a "
03003 << matrix1.rows() << " x " << matrix1.columns()
03004 << " matrix by a "
03005 << matrix0.rows() << " x " << matrix0.columns()
03006 << " matrix\n";
03007 DLR_THROW(ValueException, "matrixMultiply()", message.str().c_str());
03008 }
03009 Array2D<Type2> result = zeros(matrix0.rows(), matrix1.columns(),
03010 type_tag<Type2>());
03011 for(size_t resultRow = 0; resultRow < result.rows(); ++resultRow) {
03012 for(size_t resultColumn = 0; resultColumn < result.columns();
03013 ++resultColumn) {
03014 for(size_t index = 0; index < matrix0.columns(); ++index) {
03015 result(resultRow, resultColumn) +=
03016 (static_cast<Type2>(matrix0(resultRow, index))
03017 * static_cast<Type2>(matrix1(index, resultColumn)));
03018 }
03019 }
03020 }
03021 return result;
03022 }
03023
03024
03025
03026 template <class Type>
03027 inline Type
03028 maximum(const Array1D<Type>& array0)
03029 {
03030 return maximum(array0, std::less<Type>());
03031 }
03032
03033
03034
03035
03036 template <class Type, class Functor>
03037 Type
03038 maximum(const Array1D<Type>& array0, Functor comparator)
03039 {
03040 if(array0.size() == 0) {
03041 DLR_THROW3(ValueException, "maximum()",
03042 "Can't find the maximum element of an empty array.");
03043 }
03044 return *std::max_element(array0.begin(), array0.end(), comparator);
03045 }
03046
03047
03048
03049
03050 template <class Iterator, class Type>
03051 Type
03052 mean(const Iterator& beginIter, const Iterator& endIter)
03053 {
03054 Type meanValue;
03055 size_t count = 0;
03056 while(beginIter != endIter) {
03057 meanValue += *beginIter;
03058 ++count;
03059 ++beginIter;
03060 }
03061 return meanValue / count;
03062 }
03063
03064
03065
03066
03067 template <class Type>
03068 inline double
03069 mean(const Array1D<Type>& array0)
03070 {
03071 if(array0.size() == 0) {
03072 DLR_THROW3(ValueException, "mean()",
03073 "Can't find the mean of an empty array.");
03074 }
03075 NumericTypeConversionFunctor<typename NumericTraits<Type>::SumType,
03076 Type> functor;
03077 return functor(
03078 mean(array0, type_tag<typename NumericTraits<Type>::SumType>()));
03079 }
03080
03081
03082
03083
03084
03085 template <class Type0, class Type1>
03086 inline Type1
03087 mean(const Array1D<Type0>& array0, type_tag<Type1>)
03088 {
03089 return sum(array0, type_tag<Type1>()) / static_cast<Type1>(array0.size());
03090 }
03091
03092
03093
03094
03095
03096 template <class Type>
03097 void
03098 getMeanAndCovariance(const Array2D<Type>& sampleArray,
03099 Array1D<double>& meanArray,
03100 Array2D<double>& covarianceArray,
03101 size_t majorAxis)
03102 {
03103
03104 if(sampleArray.size() == 0) {
03105 meanArray.reinit(0);
03106 covarianceArray.reinit(0, 0);
03107 return;
03108 }
03109
03110
03111 size_t dimensionality;
03112 size_t numberOfSamples;
03113 if(majorAxis == 0) {
03114 dimensionality = sampleArray.columns();
03115 numberOfSamples = sampleArray.rows();
03116 } else {
03117 dimensionality = sampleArray.rows();
03118 numberOfSamples = sampleArray.columns();
03119 }
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138 meanArray.reinit(dimensionality);
03139 meanArray = 0.0;
03140 covarianceArray.reinit(dimensionality, dimensionality);
03141 covarianceArray = 0.0;
03142 typename Array2D<Type>::const_iterator sampleIterator =
03143 sampleArray.begin();
03144
03145 if(majorAxis == 0) {
03146 for(size_t rowIndex = 0; rowIndex < sampleArray.rows(); ++rowIndex) {
03147 for(size_t columnIndex = 0; columnIndex < sampleArray.columns();
03148 ++columnIndex) {
03149
03150 meanArray[columnIndex] += *sampleIterator;
03151
03152
03153
03154 typename Array2D<Type>::const_iterator sampleIterator2 =
03155 sampleIterator;
03156 for(size_t covarianceIndex = columnIndex;
03157 covarianceIndex < dimensionality;
03158 ++covarianceIndex) {
03159
03160 covarianceArray(columnIndex, covarianceIndex) +=
03161 *sampleIterator * *sampleIterator2;
03162 ++sampleIterator2;
03163 }
03164 ++sampleIterator;
03165 }
03166 }
03167 } else {
03168 for(size_t rowIndex = 0; rowIndex < sampleArray.rows(); ++rowIndex) {
03169 for(size_t columnIndex = 0; columnIndex < sampleArray.columns();
03170 ++columnIndex) {
03171
03172 meanArray[rowIndex] += *sampleIterator;
03173
03174
03175
03176 typename Array2D<Type>::const_iterator sampleIterator2 =
03177 sampleIterator;
03178 for(size_t covarianceIndex = rowIndex;
03179 covarianceIndex < dimensionality;
03180 ++covarianceIndex) {
03181
03182 covarianceArray(rowIndex, covarianceIndex) +=
03183 *sampleIterator * *sampleIterator2;
03184 sampleIterator2 += numberOfSamples;
03185 }
03186 ++sampleIterator;
03187 }
03188 }
03189 }
03190
03191
03192 meanArray /= static_cast<double>(numberOfSamples);
03193
03194
03195 for(size_t index0 = 0; index0 < dimensionality; ++index0) {
03196 for(size_t index1 = index0; index1 < dimensionality; ++index1) {
03197
03198 covarianceArray(index0, index1) -=
03199 numberOfSamples * meanArray[index0] * meanArray[index1];
03200 covarianceArray(index0, index1) /= (numberOfSamples - 1);
03201
03202
03203 if(index0 != index1) {
03204 covarianceArray(index1, index0) = covarianceArray(index0, index1);
03205 }
03206 }
03207 }
03208
03209 }
03210
03211
03212
03213
03214 template <class Type>
03215 inline Type
03216 minimum(const Array1D<Type>& array0)
03217 {
03218 if(array0.size() == 0) {
03219 DLR_THROW3(ValueException, "minimum()",
03220 "Can't find the minimum element of an empty array.");
03221 }
03222 return minimum(array0, std::less<Type>());
03223 }
03224
03225
03226
03227
03228 template <class Type, class Functor>
03229 Type
03230 minimum(const Array1D<Type>& array0, Functor comparator)
03231 {
03232 return *std::min_element(array0.begin(), array0.end(), comparator);
03233 }
03234
03235
03236
03237
03238 template <class FUNCTOR>
03239 double newtonRaphson(double startPoint, FUNCTOR objectiveFunction,
03240 double epsilon, size_t maxIterations)
03241 {
03242 double argument = startPoint;
03243 for(size_t count = 0; count < maxIterations; ++count) {
03244 double result = objectiveFunction(argument);
03245 if(std::fabs(result) < epsilon) {
03246 return argument;
03247 }
03248 double resultPrime = objectiveFunction.derivative(argument);
03249 if(resultPrime == 0.0) {
03250 DLR_THROW(ValueException, "newtonRaphson()", "Zero derivative.");
03251 }
03252 argument = argument - (result / resultPrime);
03253 }
03254 DLR_THROW(ValueException, "newtonRaphson()",
03255 "Root finding failed to converge.");
03256 return 0.0;
03257 }
03258
03259
03260
03261 template <class Type>
03262 inline double
03263 normalizedCorrelation(const Array1D<Type>& signal0,
03264 const Array1D<Type>& signal1)
03265 {
03266 return normalizedCorrelation(signal0, signal1, type_tag<double>());
03267 }
03268
03269
03270
03271
03272 template <class Type, class Type2>
03273 Type2
03274 normalizedCorrelation(const Array1D<Type>& signal0,
03275 const Array1D<Type>& signal1,
03276 type_tag<Type2>)
03277 {
03278 if(signal0.size() != signal1.size()) {
03279 DLR_THROW(ValueException, "normalizedCorrelation()",
03280 "Input arrays must have the same size.");
03281 }
03282 Type2 oneOverN =
03283 static_cast<Type2>(1) / static_cast<Type2>(signal0.size());
03284 Type2 sum0 = static_cast<Type2>(0);
03285 Type2 sum1 = static_cast<Type2>(0);
03286 Type2 sum00 = static_cast<Type2>(0);
03287 Type2 sum01 = static_cast<Type2>(0);
03288 Type2 sum11 = static_cast<Type2>(0);
03289 typedef typename Array1D<Type>::const_iterator SignalIter;
03290 SignalIter iter0 = signal0.begin();
03291 SignalIter iter1 = signal1.begin();
03292 SignalIter end0 = signal0.end();
03293 while(iter0 != end0) {
03294 sum0 += *iter0;
03295 sum1 += *iter1;
03296 sum00 += (*iter0) * (*iter0);
03297 sum01 += (*iter0) * (*iter1);
03298 sum11 += (*iter1) * (*iter1);
03299 ++iter0;
03300 ++iter1;
03301 }
03302 Type2 numerator = sum01 - oneOverN * sum0 * sum1;
03303 Type2 denominator = std::sqrt((sum00 - oneOverN * sum0 * sum0)
03304 * (sum11 - oneOverN * sum1 * sum1));
03305 return numerator / denominator;
03306 }
03307
03308
03309
03310 template <class Type>
03311 inline Array1D<Type>
03312 ones(int size, type_tag<Type>)
03313 {
03314 Array1D<Type> result(size);
03315 result = 1;
03316 return result;
03317 }
03318
03319
03320
03321 template <class Type>
03322 inline Array2D<Type>
03323 ones(int rows, int columns, type_tag<Type>)
03324 {
03325 Array2D<Type> result(rows, columns);
03326 result = 1;
03327 return result;
03328 }
03329
03330
03331
03332 template <class Type>
03333 inline Array2D<typename NumericTraits<Type>::ProductType>
03334 outerProduct(const Array1D<Type>& x, const Array1D<Type>& y)
03335 {
03336 return outerProduct(
03337 x, y, type_tag<typename NumericTraits<Type>::ProductType>());
03338 }
03339
03340
03341
03342
03343 template <class Type0, class Type1, class Type2>
03344 Array2D<Type2>
03345 outerProduct(const Array1D<Type0>& x, const Array1D<Type1>& y,
03346 type_tag<Type2>)
03347 {
03348 Array2D<Type2> result(x.size(), y.size());
03349 typename Array2D<Type2>::iterator runningIterator = result.begin();
03350 typename Array1D<Type1>::const_iterator yBegin = y.begin();
03351 typename Array1D<Type1>::const_iterator yEnd = y.end();
03352 for(size_t index = 0; index < x.size(); ++index) {
03353 std::transform(yBegin, yEnd, runningIterator,
03354 std::bind2nd(std::multiplies<Type2>(), x[index]));
03355 runningIterator += y.size();
03356 }
03357 return result;
03358 }
03359
03360
03361
03362
03363 template <class Type>
03364 Array1D<Type>
03365 range(Type start, Type stop, Type stride)
03366 {
03367 if(stride == 0) {
03368 DLR_THROW3(ValueException, "range(Type, Type, Type)",
03369 "Argument \"stride\" must not be equal to 0.");
03370 }
03371 int length = static_cast<int>((stop - start) / stride);
03372 if(stride > 0) {
03373 if((length * stride) < (stop - start)) {
03374 ++length;
03375 }
03376 } else {
03377 if((length * stride) > (stop - start)) {
03378 ++length;
03379 }
03380 }
03381 Array1D<Type> result(length);
03382 for(int index = 0; index < length; ++index) {
03383 result(index) = start;
03384 start += stride;
03385 }
03386 return result;
03387 }
03388
03389
03390
03391
03392 template <class Type>
03393 inline Type
03394 rms(const Array1D<Type>& array0)
03395 {
03396 NumericTypeConversionFunctor<
03397 typename NumericTraits<Type>::SumType, Type> functor;
03398 return functor(rms(array0,
03399 type_tag<typename NumericTraits<Type>::ProductType>()));
03400 }
03401
03402
03403
03404
03405 template <class Type0, class Type1>
03406 Type1
03407 rms(const Array1D<Type0>& array0, type_tag<Type1>)
03408 {
03409 Type1 accumulator = 0;
03410 for(int index = 0; index < array0.size(); ++index) {
03411 Type1 element = static_cast<Type1>(array0[index]);
03412 accumulator += element * element;
03413 }
03414 return ::sqrt(accumulator / static_cast<Type1>(array0.size()));
03415 }
03416
03417
03418
03419 template <class Type>
03420 Array2D<Type>
03421 rowIndices(size_t rows, size_t columns, type_tag<Type>)
03422 {
03423 Array2D<Type> returnValue(rows, columns);
03424 for(size_t row=0; row < rows; ++row) {
03425 Type* rowPtr = returnValue.data(row, 0);
03426 std::fill(rowPtr, rowPtr + columns, static_cast<Type>(row));
03427 }
03428 return returnValue;
03429 }
03430
03431
03432
03433 template <class Type0, class Type1>
03434 inline bool
03435 shapeMatch(const Array1D<Type0>& array0, const Array1D<Type1>& array1)
03436 {
03437 return array0.size() == array1.size();
03438 }
03439
03440
03441
03442 template <class Type0, class Type1>
03443 inline bool
03444 shapeMatch(const Array2D<Type0>& array0, const Array2D<Type1>& array1)
03445 {
03446 return ((array0.rows() == array1.rows())
03447 && (array0.columns() == array1.columns()));
03448 }
03449
03450
03451
03452 template <class Type0, class Type1>
03453 inline bool
03454 shapeMatch(const Array3D<Type0>& array0, const Array3D<Type1>& array1)
03455 {
03456 return ((array0.shape0() == array1.shape0())
03457 && (array0.shape1() == array1.shape1())
03458 && (array0.shape2() == array1.shape2()));
03459 }
03460
03461
03462
03463 template <class Type>
03464 inline Array2D<Type>
03465 skewSymmetric(const Array1D<Type>& vector0)
03466 {
03467 if(vector0.size() != 3) {
03468 std::ostringstream message;
03469 message << "Argument must have exactly 3 elements, but instead has "
03470 << vector0.size() << "elements.";
03471 DLR_THROW(ValueException, "skewSymmetric()", message.str().c_str());
03472 }
03473 Array2D<Type> returnVal(3, 3);
03474 returnVal(0, 0) = 0;
03475 returnVal(0, 1) = -vector0(2);
03476 returnVal(0, 2) = vector0(1);
03477
03478 returnVal(1, 0) = vector0(2);
03479 returnVal(1, 1) = 0;
03480 returnVal(1, 2) = -vector0(0);
03481
03482 returnVal(2, 0) = -vector0(1);
03483 returnVal(2, 1) = vector0(0);
03484 returnVal(2, 2) = 0;
03485 return returnVal;
03486 }
03487
03488
03489
03490
03491 template <class Type>
03492 void
03493 solveQuadratic(Type c0, Type c1, Type c2,
03494 Type& root0, Type& root1, bool& valid,
03495 bool checkValidity)
03496 {
03497 Type ss = c1 * c1;
03498 ss -= (4.0 * c0 * c2);
03499 if(checkValidity) {
03500 valid = (ss >= 0.0);
03501
03502 if(!valid) {
03503 ss = 1.0;
03504 }
03505 } else {
03506 valid = true;
03507 }
03508 Type rt = std::sqrt(ss);
03509
03510
03511 if(c1 < 0.0) {
03512 rt *= -1;
03513 }
03514 Type qq = -0.5 * (rt + c1);
03515 root0 = qq / c0;
03516 root1 = c2 / qq;
03517 }
03518
03519
03520
03521
03522 template <class Type>
03523 inline double
03524 standardDeviation(const Array1D<Type>& array0)
03525 {
03526 return standardDeviation(array0, type_tag<double>());
03527 }
03528
03529
03530
03531
03532 template <class Type0, class Type1>
03533 inline Type1
03534 standardDeviation(const Array1D<Type0>& array0, type_tag<Type1>)
03535 {
03536 return ::sqrt(variance(array0, type_tag<Type1>()));
03537 }
03538
03539
03540
03541
03542 template <class Type>
03543 inline typename NumericTraits<Type>::SumType
03544 sum(const Array1D<Type>& array0)
03545 {
03546 return sum(array0, type_tag<typename NumericTraits<Type>::SumType>());
03547 }
03548
03549
03550
03551
03552 template <class Type, class Type2>
03553 Type2
03554 sum(const Array1D<Type>& array0, type_tag<Type2>)
03555 {
03556 return std::accumulate(array0.begin(), array0.end(),
03557 static_cast<Type2>(0));
03558 }
03559
03560
03561
03562
03563 template <class Type>
03564 inline typename NumericTraits<Type>::SumType
03565 sum(const Array2D<Type>& array0,
03566 const Index2D& upperLeftCorner,
03567 const Index2D& lowerRightCorner)
03568 {
03569 return sum(array0, upperLeftCorner, lowerRightCorner,
03570 type_tag<typename NumericTraits<Type>::SumType>());
03571 }
03572
03573
03574
03575
03576 template <class Type, class Type2>
03577 Type2
03578 sum(const Array2D<Type>& array0,
03579 const Index2D& upperLeftCorner,
03580 const Index2D& lowerRightCorner,
03581 type_tag<Type2> typeTag)
03582 {
03583 Type2 result = static_cast<Type2>(0);
03584 for(int row = upperLeftCorner.getRow();
03585 row < lowerRightCorner.getRow();
03586 ++row) {
03587 typename Array2D<Type>::const_iterator rowBegin = array0.rowBegin(row);
03588 result += std::accumulate(
03589 rowBegin + upperLeftCorner.getColumn(),
03590 rowBegin + lowerRightCorner.getColumn(),
03591 static_cast<Type2>(0));
03592 }
03593 return result;
03594 }
03595
03596
03597
03598
03599 template <class Type>
03600 inline double
03601 variance(const Array1D<Type>& array0)
03602 {
03603 return variance(array0, type_tag<double>());
03604 }
03605
03606
03607
03608
03609 template <class Type0, class Type1>
03610 inline Type1
03611 variance(const Array1D<Type0>& array0, type_tag<Type1>)
03612 {
03613 Type1 meanValue = mean(array0, type_tag<Type1>());
03614 Type1 accumulator = 0;
03615 for(size_t index0 = 0; index0 < array0.size(); ++index0) {
03616 Type1 offset = static_cast<Type1>(array0[index0]) - meanValue;
03617 accumulator += offset * offset;
03618 }
03619 return accumulator / static_cast<Type1>(array0.size());
03620 }
03621
03622
03623
03624 template <class Type>
03625 inline Array1D<Type>
03626 zeros(size_t size, type_tag<Type>)
03627 {
03628 Array1D<Type> result(size);
03629 result = 0;
03630 return result;
03631 }
03632
03633
03634
03635 template <class Type>
03636 inline Array2D<Type>
03637 zeros(size_t rows, size_t columns, type_tag<Type>)
03638 {
03639 Array2D<Type> result(rows, columns);
03640 result = 0;
03641 return result;
03642 }
03643
03644
03645
03646
03647 template <class Type>
03648 inline Array3D<Type>
03649 zeros(size_t shape0, size_t shape1, size_t shape2, type_tag<Type>)
03650 {
03651 Array3D<Type> result(shape0, shape1, shape2);
03652 result = 0;
03653 return result;
03654 }
03655
03656 }
03657
03658 }
03659
03660 #endif