00001
00216
00217
00218
00219 #ifndef __ARRAYOP_H
00220 #define __ARRAYOP_H
00221
00222
00223 #include <cmath>
00224 #include <Array/Array.h>
00225
00226
00227
00250 template < class T >
00251 inline bool operator == (const Array< T >& v, const Array< T >& w)
00252 {
00253
00254 if (!v.samedim(w)) return false;
00255 typename Array<T>::iterator iterV, iterW;
00256 for (iterV = v.begin(), iterW = w.begin(); iterV != v.end();
00257 iterV++, iterW++) {
00258 if (*iterV != *iterW) return false;
00259 }
00260 return true;
00261 }
00262
00263
00264
00287 template < class T >
00288 inline bool operator == (const ArrayReference< T > v, const Array< T >& w)
00289 {
00290 if (!v.samedim(w)) return false;
00291 typename Array<T>::iterator iterV, iterW;
00292 for (iterV = v.begin(), iterW = w.begin(); iterV != v.end();
00293 iterV++, iterW++) {
00294 if (*iterV != *iterW) return false;
00295 }
00296 return true;
00297 }
00298
00299
00300
00323 template < class T >
00324 inline bool operator == (const Array< T >& v, const ArrayReference< T > w)
00325 {
00326 if (!v.samedim(w)) return false;
00327 typename Array<T>::iterator iterV, iterW;
00328 for (iterV = v.begin(), iterW = w.begin(); iterV != v.end();
00329 iterV++, iterW++) {
00330 if (*iterV != *iterW) return false;
00331 }
00332 return true;
00333 }
00334
00335
00336
00350 template < class T >
00351 inline bool operator == (const ArrayReference< T > v, const ArrayReference< T > w)
00352 {
00353 if (!v.samedim(w)) return false;
00354 typename Array<T>::iterator iterV, iterW;
00355 for (iterV = v.begin(), iterW = w.begin(); iterV != v.end();
00356 iterV++, iterW++) {
00357 if (*iterV != *iterW) return false;
00358 }
00359 return true;
00360 }
00361
00362
00363
00388 template < class T >
00389 inline bool operator < (const Array< T >& v, const Array< T >& w)
00390 {
00391 if (v.nelem() == w.nelem()) {
00392
00393 for (unsigned i = 0; i < v.nelem(); ++i)
00394 if (w.elem(i) < v.elem(i))
00395 return false;
00396
00397 else if (v.elem(i) < w.elem(i))
00398 return true;
00399
00400 }
00401
00402 return v.nelem() < w.nelem();
00403 }
00404
00405
00406
00430 template < class T >
00431 inline bool operator != (const Array< T >& v, const Array< T >& w)
00432 {
00433 return !(v == w);
00434 }
00435
00436
00437
00438
00462 template < class T >
00463 inline bool operator != (const ArrayReference< T > v, const Array< T >& w)
00464 {
00465 return !(v == w);
00466 }
00467
00468
00492 template < class T >
00493 inline bool operator != (const Array< T >& v, const ArrayReference< T > w)
00494 {
00495
00496 return !(v == w);
00497 }
00498
00499
00500
00515 template < class T >
00516 inline bool operator != (const ArrayReference< T > v, const ArrayReference< T > w)
00517 {
00518 return !(v == w);
00519 }
00520
00521
00522
00523
00574 template < class T >
00575 inline Array< T > innerProduct(const Array< T >& v, const Array< T >& w)
00576 {
00577 unsigned vd = v.ndim();
00578 unsigned wd = w.ndim();
00579 unsigned zd = vd + wd - 2;
00580 unsigned i, j, k;
00581 T t;
00582 Array< T > z;
00583
00584
00585
00586
00587 if (vd == 0 || wd == 0) {
00588 if (vd == 0 && v.nelem() == 1) {
00589 return w * v.elem(0);
00590 }
00591 else if (wd == 0 && w.nelem() == 1) {
00592 return w.elem(0) * v;
00593 }
00594 else {
00595 return Array< T >();
00596 }
00597 }
00598
00599 else if (vd == 1 && wd == 1) {
00600 t = scalarProduct(v, w);
00601 z.resize(1);
00602 z(0) = t;
00603 return Array< T >(z, true);
00604 }
00605
00606 SIZE_CHECK(v.dim(vd - 1) == w.dim(0))
00607
00608 std::vector< unsigned > dim(zd);
00609
00610 for (i = j = 0; j < vd - 1; dim[ i++ ] = v.dim(j++));
00611 for (j = 1; j < wd ; dim[ i++ ] = w.dim(j++));
00612
00613 z.resize(dim);
00614
00615 std::vector< unsigned > vdim(vd);
00616 std::vector< unsigned > wdim(wd);
00617
00618 std::vector< unsigned > zdim(zd, 0U);
00619
00620 do {
00621 for (i = j = 0; j < vd - 1; vdim[ j++ ] = zdim[ i++ ]);
00622 for (j = 1; j < wd ; wdim[ j++ ] = zdim[ i++ ]);
00623 for (t = T(0), k = 0; k < w.dim(0); k++) {
00624 vdim[ vd-1 ] = wdim[ 0 ] = k;
00625 t += v(vdim) * w(wdim);
00626 }
00627 z(zdim) = t;
00628
00629 for (i = 0; i < zd && ++zdim[ i ] >= z.dim(i); zdim[ i++ ] = 0);
00630 }
00631 while (i < zd);
00632
00633 return Array< T >(z, true);
00634 }
00635
00636
00637
00676 template < class T >
00677 inline Array< T > outerProduct(const Array< T >& v, const Array< T >& w)
00678 {
00679 unsigned vd = v.ndim();
00680 unsigned wd = w.ndim();
00681 unsigned zd;
00682
00683
00684
00685
00686 if (vd == 0 || wd == 0) {
00687 if (vd == 0 && v.nelem() == 1) {
00688 return w * v.elem(0);
00689 }
00690 else if (wd == 0 && w.nelem() == 1) {
00691 return w.elem(0) * v;
00692 }
00693 else {
00694 return Array< T >();
00695 }
00696 }
00697
00698 unsigned i, j;
00699
00700 std::vector< unsigned > dim(zd = vd + wd);
00701
00702 for (i = j = 0; j < vd; dim[ i++ ] = v.dim(j++));
00703 for (j = 0; j < wd; dim[ i++ ] = w.dim(j++));
00704
00705 Array< T > z;
00706 z.resize(dim);
00707
00708 std::vector< unsigned > vdim(vd);
00709 std::vector< unsigned > wdim(wd);
00710 std::vector< unsigned > zdim(zd, 0U);
00711
00712 do {
00713 for (i = j = 0; j < vd; vdim[ j++ ] = zdim[ i++ ]);
00714
00715 for (j = 0; j < wd; wdim[ j++ ] = zdim[ i++ ]);
00716
00717 z(zdim) = v(vdim) * w(wdim);
00718
00719 for (i = 0; i < zd && ++zdim[ i ] >= z.dim(i); zdim[ i++ ] = 0);
00720 }
00721 while (i < zd);
00722
00723 return Array< T >(z, true);
00724 }
00725
00726
00727
00766 template < class T >
00767 inline T scalarProduct(const Array< T >& v, const Array< T >& w)
00768 {
00769 SIZE_CHECK(v.samedim(w))
00770
00771 T t(0);
00772 for (unsigned i = v.nelem(); i--; t += v.elem(i) * w.elem(i));
00773 return t;
00774 }
00775
00776
00777
00810 template < class T >
00811 inline T sqrDistance(const Array< T >& v, const Array< T >& w)
00812 {
00813 SIZE_CHECK(v.samedim(w))
00814
00815 T d, t(0);
00816 for (unsigned i = v.nelem(); i--;) {
00817 d = v.elem(i) - w.elem(i);
00818 t += d * d;
00819 }
00820
00821 return t;
00822 }
00823
00824
00825
00858 template < class T >
00859 inline T euclidianDistance(const Array< T >& v, const Array< T >& w)
00860 {
00861 return sqrt(sqrDistance(v, w));
00862 }
00863
00864
00865
00893 template < class T >
00894 inline T sum(const Array< T >& v)
00895 {
00896 T t(0);
00897 for (unsigned i = v.nelem(); i--; t += v.elem(i));
00898 return t;
00899 }
00900
00901
00929 template < class T >
00930 inline T sumOfAbs(const Array< T >& v)
00931 {
00932 T t(0);
00933 for (unsigned i = v.nelem(); i--; t += fabs(v.elem(i)));
00934 return t;
00935 }
00936
00937
00938
00966 template < class T >
00967 inline T sumOfSqr(const Array< T >& v)
00968 {
00969 T t(0);
00970 for (unsigned i = v.nelem(); i--; t += v.elem(i) * v.elem(i));
00971 return t;
00972 }
00973
00974
00975
01003 template < class T >
01004 inline T product(const Array< T >& v)
01005 {
01006 T t(1);
01007 for (unsigned i = v.nelem(); i--; t *= v.elem(i));
01008 return t;
01009 }
01010
01011
01012
01033 template < class T >
01034 inline T minElement(const Array< T >& v)
01035 {
01036 RANGE_CHECK(v.nelem() > 0)
01037
01038 T t(v.elem(0));
01039
01040 for (unsigned i = 1; i < v.nelem(); ++i)
01041 if (v.elem(i) < t) t = v.elem(i);
01042
01043 return t;
01044 }
01045
01046
01047
01092 template < class T >
01093 inline T minElement(const Array< T >& v, unsigned & ind,
01094 unsigned start = 0, unsigned end = 0)
01095 {
01096 RANGE_CHECK(v.nelem() > 0)
01097 RANGE_CHECK(v.nelem() > start)
01098 RANGE_CHECK(v.nelem() >= end)
01099
01100 RANGE_CHECK(end >= start)
01101
01102 T t(v.elem(start));
01103 ind = start;
01104 if (end == 0) {
01105 end = v.nelem();
01106 }
01107 for (unsigned i = start; i < end; ++i)
01108 if (v.elem(i) < t) {
01109 t = v.elem(i);
01110 ind = long(i);
01111 }
01112
01113 return t;
01114 }
01115
01116
01117
01138 template < class T >
01139 inline T maxElement(const Array< T >& v)
01140 {
01141 RANGE_CHECK(v.nelem() > 0)
01142
01143 T t(v.elem(0));
01144
01145 for (unsigned i = 1; i < v.nelem(); ++i)
01146 if (v.elem(i) > t) t = v.elem(i);
01147
01148 return t;
01149 }
01150
01151
01152
01197 template < class T >
01198 inline T maxElement(const Array< T >& v, unsigned & ind,
01199 unsigned start = 0, unsigned end = 0)
01200 {
01201 RANGE_CHECK(v.nelem() > 0)
01202 RANGE_CHECK(v.nelem() > start)
01203 RANGE_CHECK(v.nelem() >= end)
01204
01205 RANGE_CHECK(end >= start)
01206
01207 T t(v.elem(start));
01208 ind = start;
01209 if (end == 0) {
01210 end = v.nelem();
01211 }
01212 for (unsigned i = start; i < end; ++i)
01213 if (v.elem(i) > t) {
01214 t = v.elem(i);
01215 ind = long(i);
01216 }
01217
01218 return t;
01219 }
01220
01221
01222
01243 template < class T >
01244 inline void minmaxElement(const Array< T >& v, T& minVal, T& maxVal)
01245 {
01246 if (v.nelem() > 0) {
01247 minVal = maxVal = v.elem(0);
01248
01249 for (unsigned i = 1; i < v.nelem(); ++i) {
01250 if (v.elem(i) < minVal)
01251 minVal = v.elem(i);
01252 else if (v.elem(i) > maxVal)
01253 maxVal = v.elem(i);
01254 }
01255 }
01256 }
01257
01258
01259
01334 template < class T >
01335 bool prettyprint(std::ostream& os, const Array< T >& v, unsigned depth = 0)
01336 {
01337 unsigned i, j;
01338 bool nl;
01339
01340 if (v.ndim() == 0) {
01341 os << v.elem(0) << " ";
01342 return false;
01343 }
01344 else if (v.ndim() == 1) {
01345 os << "( ";
01346 for (i = 0; i < v.dim(0); i++)
01347 prettyprint(os, v[ i ], depth + 1);
01348 os << ") ";
01349 return true;
01350 }
01351 else {
01352 os << "( ";
01353 i = 0;
01354 nl = prettyprint(os, v[ i++ ], depth + 1);
01355 while (i < v.dim(0)) {
01356 if (nl) {
01357 os << "\n ";
01358 for (j = 0; j < depth; j++) os << " ";
01359 }
01360 nl = prettyprint(os, v[ i++ ], depth + 1);
01361 }
01362 os << ") ";
01363 return nl;
01364 }
01365 }
01366
01367 #ifdef __ARRAY_NO_GENERIC_IOSTREAM
01368
01369
01370
01409 template < class T >
01410 inline std::istream& operator >> (std::istream& is, Array< T >& a)
01411 {
01412 const unsigned MaxLen = 1024;
01413 char s[ MaxLen ];
01414 char* p;
01415 unsigned i;
01416 std::vector< unsigned > idx;
01417
01418 is >> std::ws;
01419 is.getline(s, MaxLen);
01420
01421 p = strchr(s, '>');
01422 if (p && *p) p++;
01423 if (p && *p) p++;
01424
01425 TYPE_CHECK(p && *p)
01426 if (p && *p) {
01427 do {
01428 if (*p == ',') p++;
01429 idx.push_back(unsigned(strtol(p, &p, 10)));
01430 }
01431 while (p && *p == ',');
01432
01433 TYPE_CHECK(p && *p == ')')
01434
01435 a.resize(idx);
01436
01437 for (i = 0; i < a.nelem() && is.good(); i++)
01438 is >> a.elem(i);
01439 }
01440
01441 return is >> std::ws;
01442 }
01443
01444
01445
01505 template < class T >
01506 inline std::ostream& operator << (std::ostream& os, const Array< T >& a)
01507 {
01508 unsigned i;
01509
01510 os << "Array<" << typeid(T).name() << ">(";
01511 for (i = 0; i < a.ndim(); ++i) {
01512 if (i) os << ',';
01513 os << a.dim(i);
01514 }
01515 os << ")\n";
01516
01517 for (i = 0; i < a.nelem(); ++i) {
01518 if (i) os << '\t';
01519 os << a.elem(i);
01520 }
01521
01522 return os << std::endl;
01523 }
01524 #endif // __ARRAY_NO_GENERIC_IOSTREAM
01525
01526
01527
01552 template < class T >
01553 inline void clip
01554 (
01555 Array< T >& valArrA,
01556 const T& lowerBoundA,
01557 const T& upperBoundA
01558 )
01559 {
01560 for (unsigned i = valArrA.nelem(); i--;) {
01561 if (valArrA.elem(i) < lowerBoundA) {
01562 valArrA.elem(i) = lowerBoundA;
01563 }
01564 else if (valArrA.elem(i) > upperBoundA) {
01565 valArrA.elem(i) = upperBoundA;
01566 }
01567 }
01568 }
01569
01570
01571 #ifndef DOXYGEN
01572
01573
01574 #define UnaryOperator( op ) \
01575 template < class T > \
01576 inline Array< T > operator op ( const Array< T >& v ) \
01577 { \
01578 Array< T > z; \
01579 \
01580 z.resize( v ); \
01581 typename Array<T>::iterator iterZ; \
01582 typename Array<T>::iterator iterV; \
01583 for(iterV = v.begin(), iterZ = z.begin(); iterV != v.end(); \
01584 iterV++, iterZ++) \
01585 { \
01586 *iterZ = op *iterV; \
01587 } \
01588 \
01589 return Array< T >( z, true ); \
01590 }
01591
01592
01593 UnaryOperator(!)
01594
01595
01596 UnaryOperator(~)
01597
01598
01599 UnaryOperator( +)
01600
01601
01602 UnaryOperator(-)
01603
01604 #undef UnaryOperator
01605
01606
01607
01608 #define BinaryOperator( op ) \
01609 template < class T > \
01610 inline Array< T > operator op ( const Array< T >& v, const Array< T >& w ) \
01611 { \
01612 SIZE_CHECK( v.samedim( w ) ) \
01613 \
01614 Array< T > z; \
01615 z.resize( v ); \
01616 \
01617 typename Array<T>::iterator iterZ; \
01618 typename Array<T>::iterator iterW; \
01619 typename Array<T>::iterator iterV; \
01620 for(iterV = v.begin(), iterW = w.begin(), iterZ = z.begin(); \
01621 iterV != v.end(); iterV++, iterW++, iterZ++) \
01622 { \
01623 *iterZ = *iterV op *iterW; \
01624 } \
01625 \
01626 return Array< T >( z, true ); \
01627 } \
01628 \
01629 template < class T > \
01630 inline Array< T > operator op ( const Array< T >& v, T w ) \
01631 { \
01632 Array< T > z; \
01633 z.resize( v ); \
01634 \
01635 typename Array<T>::iterator iterZ; \
01636 typename Array<T>::iterator iterV; \
01637 for(iterV = v.begin(), iterZ = z.begin(); \
01638 iterV != v.end(); iterV++, iterZ++) \
01639 { \
01640 *iterZ = *iterV op w; \
01641 } \
01642 \
01643 return Array< T >( z, true ); \
01644 } \
01645 \
01646 template < class T > \
01647 inline Array< T > operator op ( T v, const Array< T >& w ) \
01648 { \
01649 Array< T > z; \
01650 z.resize( w ); \
01651 \
01652 typename Array<T>::iterator iterZ; \
01653 typename Array<T>::iterator iterW; \
01654 for(iterW = w.begin(), iterZ = z.begin(); \
01655 iterW != w.end(); iterW++, iterZ++) \
01656 { \
01657 *iterZ = v op *iterW; \
01658 } \
01659 \
01660 return Array< T >( z, true ); \
01661 }
01662
01663
01664
01665 BinaryOperator( ||)
01666
01667
01668
01669 BinaryOperator( &&)
01670
01671
01672
01673 BinaryOperator( |)
01674
01675
01676
01677 BinaryOperator( ^)
01678
01679
01680
01681 BinaryOperator(&)
01682
01683
01684
01685 BinaryOperator( +)
01686
01687
01688
01689 BinaryOperator(-)
01690
01691
01692
01693 BinaryOperator(*)
01694
01695
01696
01697 BinaryOperator( /)
01698
01699
01700
01701 BinaryOperator( %)
01702
01703 #undef BinaryOperator
01704
01705
01706 #define CompoundAssignmentOperator( op ) \
01707 template < class T, class S > \
01708 inline Array< T >& operator op ( Array< T >& v, const Array< S >& w ) \
01709 { \
01710 SIZE_CHECK( v.samedim( w ) ) \
01711 \
01712 typename Array<S>::iterator iterW; \
01713 typename Array<T>::iterator iterV; \
01714 for(iterV = v.begin(), iterW = w.begin(); \
01715 iterV != v.end(); iterV++, iterW++) \
01716 { \
01717 *iterV op *iterW; \
01718 } \
01719 \
01720 return v; \
01721 } \
01722 \
01723 template < class T > \
01724 inline Array< T >& operator op ( Array< T >& v, T w ) \
01725 { \
01726 typename Array<T>::iterator iterV; \
01727 for(iterV = v.begin(); iterV != v.end(); iterV++) \
01728 { \
01729 *iterV op w; \
01730 } \
01731 \
01732 return v; \
01733 } \
01734 \
01735 template < class T > \
01736 inline ArrayReference< T > operator op ( ArrayReference< T > v, \
01737 const Array< T >& w ) \
01738 { \
01739 SIZE_CHECK( v.samedim( w ) ) \
01740 \
01741 typename Array<T>::iterator iterW; \
01742 typename Array<T>::iterator iterV; \
01743 for(iterV = v.begin(), iterW = w.begin(); \
01744 iterV != v.end(); iterV++, iterW++) \
01745 { \
01746 *iterV op *iterW; \
01747 } \
01748 \
01749 return v; \
01750 } \
01751 \
01752 template < class T > \
01753 inline ArrayReference< T > operator op ( ArrayReference< T > v, T w ) \
01754 { \
01755 typename Array<T>::iterator iterV; \
01756 for(iterV = v.begin(); iterV != v.end(); iterV++) \
01757 { \
01758 *iterV op w; \
01759 } \
01760 \
01761 return v; \
01762 }
01763
01764
01765
01766 CompoundAssignmentOperator( |=)
01767
01768
01769
01770 CompoundAssignmentOperator( ^=)
01771
01772
01773
01774 CompoundAssignmentOperator( &=)
01775
01776
01777
01778 CompoundAssignmentOperator( +=)
01779
01780
01781
01782 CompoundAssignmentOperator( -=)
01783
01784
01785
01786 CompoundAssignmentOperator( *=)
01787
01788
01789
01790 CompoundAssignmentOperator( /=)
01791
01792
01793
01794 CompoundAssignmentOperator( %=)
01795
01796 #undef CompoundAssignmentOperator
01797
01798
01799 #define UnaryFunction( func ) \
01800 template < class T > \
01801 inline Array< T > func ( const Array< T >& v ) \
01802 { \
01803 Array< T > z; \
01804 z.resize( v ); \
01805 \
01806 typename Array<T>::iterator iterZ; \
01807 typename Array<T>::iterator iterV; \
01808 for(iterV = v.begin(), iterZ = z.begin(); iterV != v.end(); \
01809 iterV++, iterZ++) \
01810 { \
01811 *iterZ = func( *iterV ); \
01812 } \
01813 \
01814 return Array< T >( z, true ); \
01815 }
01816
01817
01818
01819
01820
01821
01822 UnaryFunction(acos)
01823
01824
01825
01826 UnaryFunction(asin)
01827
01828
01829
01830 UnaryFunction(atan)
01831
01832
01833
01834 UnaryFunction(cos)
01835
01836
01837
01838 UnaryFunction(sin)
01839
01840
01841
01842 UnaryFunction(tan)
01843
01844
01845
01846
01847
01848
01849
01850 UnaryFunction(cosh)
01851
01852
01853
01854 UnaryFunction(sinh)
01855
01856
01857
01858 UnaryFunction(tanh)
01859
01860
01861
01862 UnaryFunction(acosh)
01863
01864
01865
01866 UnaryFunction(asinh)
01867
01868
01869
01870 UnaryFunction(atanh)
01871
01872
01873
01874
01875
01876
01877
01878 UnaryFunction(exp)
01879
01880
01881
01882 UnaryFunction(log)
01883
01884
01885
01886 UnaryFunction(log10)
01887
01888
01889
01890
01891
01892
01893
01894 UnaryFunction(sqrt)
01895
01896
01897
01898 UnaryFunction(cbrt)
01899
01900
01901
01902
01903
01904
01905
01906 UnaryFunction(ceil)
01907
01908
01909
01910 UnaryFunction(fabs)
01911
01912
01913
01914 UnaryFunction(floor)
01915
01916 #undef UnaryFunction
01917
01918
01919 #define BinaryFunction( func ) \
01920 template < class T > \
01921 inline Array< T > func( const Array< T >& v, const Array< T >& w ) \
01922 { \
01923 SIZE_CHECK( v.samedim( w ) ) \
01924 \
01925 Array< T > z; \
01926 z.resize( v ); \
01927 \
01928 for( unsigned i = z.nelem( ); i--; ) \
01929 z.elem( i ) = func( v.elem( i ), w.elem( i ) ); \
01930 \
01931 return Array< T >( z, true ); \
01932 } \
01933 \
01934 template < class T > \
01935 inline Array< T > func( const Array< T >& v, T w ) \
01936 { \
01937 Array< T > z; \
01938 z.resize( v ); \
01939 \
01940 for( unsigned i = z.nelem( ); i--; ) \
01941 z.elem( i ) = func( v.elem( i ), w ); \
01942 \
01943 return Array< T >( z, true ); \
01944 } \
01945 \
01946 template < class T > \
01947 inline Array< T > func( T v, const Array< T >& w ) \
01948 { \
01949 Array< T > z; \
01950 z.resize( w ); \
01951 \
01952 for( unsigned i = z.nelem( ); i--; ) \
01953 z.elem( i ) = func( v, w.elem( i ) ); \
01954 \
01955 return Array< T >( z, true ); \
01956 }
01957
01958
01959
01960
01961
01962 BinaryFunction(atan2)
01963
01964
01965
01966 BinaryFunction(pow)
01967
01968
01969
01970 BinaryFunction(fmod)
01971
01972 #undef BinaryFunction
01973
01974
01975 #endif
01976
01977
01978
01979
01980 #endif
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990