00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef __OPENKN_MATH__VECTOR_HPP__
00027 #define __OPENKN_MATH__VECTOR_HPP__
00028
00029
00030 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00031 #pragma warning(disable:4996)
00032 #endif
00033
00034
00035
00036
00037 #include <iostream>
00038 #include <algorithm>
00039 #include <numeric>
00040 #include <cmath>
00041
00042
00043
00044
00045
00046 #include "MathException.hpp"
00047
00048
00049
00050
00051
00052 namespace kn{
00053
00054
00055
00056
00057
00061 template<class T>
00062 class Vector {
00063
00064
00065
00066
00067 protected :
00071 size_t sizeVector;
00072
00076 T *begin_;
00077
00081 T *end_;
00082
00086 T *data;
00087
00088
00089
00090
00091
00092 public:
00093
00097 Vector();
00098
00103 explicit Vector(const size_t& size);
00104
00109 Vector(const Vector<T> & v);
00110
00115 Vector(Vector<T> * v);
00116
00123 Vector(const size_t& dataSize,
00124 const T *a);
00125
00131 Vector(const size_t& dataSize,
00132 const T &d);
00133
00134
00135
00136
00137 protected :
00141 void allocate(const size_t& d);
00142
00146 inline void desallocate(void){
00147 if(sizeVector != 0 && data != 0) delete[] data;
00148 sizeVector = 0;
00149 }
00150
00151
00152
00153
00154 public :
00155
00159 virtual inline ~Vector(void){
00160 desallocate();
00161 }
00162
00169 T& at(const unsigned int& i);
00170
00177 const T& at(const unsigned int& i) const;
00178
00183 void resize(const int& size);
00184
00190 void resizeAndCopy(const Vector<T>& v);
00191
00192
00193
00194
00200 bool operator==(const Vector<T>& v) const;
00201
00207 inline bool operator!=(const Vector<T>& v) const{
00208 return !(*this == v);
00209 }
00210
00217 Vector<T>& operator=(const Vector<T>& v);
00218
00224 Vector<T>& operator=(const T & value);
00225
00232 Vector<T> operator+(const Vector<T>& v) const;
00233
00234
00240 Vector<T> operator-(const Vector<T>& v) const;
00241
00248 inline Vector<T> operator/(const T& d) const{
00249 return Vector(*this) /= d;
00250 }
00251
00258 T operator*(const Vector<T>& v) const;
00259
00266 inline T dot(const Vector<T>& v) const{
00267 return (*this)*v;
00268 }
00269
00275 inline Vector<T> operator*(const T& d) const{
00276 return Vector(*this) *= d;
00277 }
00278
00283 inline Vector<T> operator-(void)const{
00284 return Vector<T>(*this) * ((T)(-1));
00285 }
00286
00293 Vector<T>& operator+=(const Vector<T>& v);
00294
00301 Vector<T>& operator-=(const Vector<T>& v);
00302
00310 Vector<T>& operator/=(const T& d);
00311
00317 Vector<T>& operator*=(const T& d);
00318
00324 T& operator[](const unsigned int& i);
00325
00331 const T& operator[](const unsigned int& i) const;
00332
00338 T& operator()(const unsigned int& i);
00339
00345 const T& operator()(const unsigned int& i) const;
00346
00353 Vector<T> operator^(const Vector<T>& v)const;
00354
00361 inline Vector<T> cross(const Vector<T>& v)const{
00362 return (*this)^v;
00363 }
00364
00365
00366
00367
00368
00369
00370
00375 inline size_t size(void) const{
00376 return sizeVector;
00377 }
00378
00382 inline void fill(const T &d){
00383 std::fill(begin_,end_,d);
00384 }
00385
00389 inline void setZero(void){
00390 fill(T(0.0));
00391 }
00392
00397 void roundZero(const double & d = 1.0e-14);
00398
00407 void setSubVector(const unsigned int& index, const Vector<T>& v);
00408
00420 void setSubVector(const unsigned int& index1, const unsigned int& index2,const unsigned int& size, const Vector<T>& v);
00428 Vector<T> getSubVector(const unsigned int& index, const int& size) const;
00429
00430
00435 inline virtual T* begin(void) const{
00436 return begin_;
00437 }
00438
00439
00444 inline virtual T* end(void) const{
00445 return end_;
00446 }
00447
00448
00453 double getNorm(void) const;
00454
00459 Vector<T>& normalize(void);
00460
00464 Vector<T> getNormalized(void) const;
00465
00472 void swap(const unsigned int& index1, const unsigned int& index2);
00473
00479 Vector<T> getHomogeneous(const T &d = T(1.0)) const;
00480
00481
00487 Vector<T> getUnhomogeneous(const T &zeroValue = T(1.0e-13)) const;
00488
00489
00495 void setHomogeneousNormalForm(const T &zeroValue = T(1.0e-13)) const;
00496
00497 };
00498
00499 template<class T>
00500 Vector<T>::Vector(){
00501 sizeVector = 0;
00502 }
00503
00504 template<class T>
00505 Vector<T>::Vector(const size_t& size){
00506 allocate(size);
00507 setZero();
00508 }
00509
00510 template<class T>
00511 Vector<T>::Vector(const Vector<T> & v){
00512 allocate(v.sizeVector);
00513
00514 std::copy(v.begin_, v.end_, begin_);
00515 }
00516
00517
00518 template<class T>
00519 Vector<T>::Vector(Vector<T> * v){
00520 if(v == 0) throw MathException("Null pointer exception");
00521
00522 allocate(v->sizeVector);
00523
00524 std::copy(v->begin_, v->end_, this->begin_);
00525 }
00526
00527 template<class T>
00528 Vector<T>::Vector(const size_t& dataSize,
00529 const T *a){
00530 if(a == 0) throw MathException("Null pointer exception");
00531
00532 allocate(dataSize);
00533
00534 std::copy(a,a+dataSize,this->begin_);
00535 }
00536
00537
00538 template<class T>
00539 Vector<T>::Vector(const size_t& dataSize,
00540 const T &d){
00541 allocate(dataSize);
00542 fill(d);
00543 }
00544
00545 template<class T>
00546 void Vector<T>::resize(const int& size){
00547 if(sizeVector != size) desallocate();
00548 if(sizeVector == 0) allocate(size);
00549 std::fill(begin_, end_, T(0));
00550 }
00551
00552 template<class T>
00553 void Vector<T>::resizeAndCopy(const Vector<T>& v){
00554 if(&v == this) return;
00555 if(sizeVector != v.sizeVector) desallocate();
00556 if(sizeVector == 0) allocate(v.sizeVector);
00557 std::copy(v.begin_, v.end_, begin_);
00558 }
00559
00560 template<class T>
00561 void Vector<T>::allocate(const size_t& d){
00562 if(d == 0) throw MathException("vector size is 0");
00563
00564 sizeVector = d;
00565 data = new T[d];
00566 begin_ = data;
00567 end_ = begin_ + d;
00568 }
00569
00570 template<class T>
00571 T& Vector<T>::at(const unsigned int& i){
00572 if(i >= sizeVector) throw MathException("Index out of bounds");
00573 return data[i];
00574 }
00575
00576 template<class T>
00577 const T& Vector<T>::at(const unsigned int& i) const{
00578 if(i >= sizeVector) throw MathException("Index out of bounds");
00579 return data[i];
00580 }
00581
00582 template<class T>
00583 bool Vector<T>::operator==(const Vector<T>& v) const{
00584 if(v.sizeVector != sizeVector) return false;
00585
00586 return std::equal(begin_, end_, v.begin_);
00587 }
00588
00589
00590 template<class T>
00591 Vector<T>& Vector<T>::operator=(const Vector<T>& v){
00592 if(&v == this) return *this;
00593
00594 if(sizeVector == 0) allocate(v.sizeVector);
00595
00596 if(sizeVector != v.sizeVector) throw MathException("incompatible vector size");
00597
00598 std::copy(v.begin_, v.end_, begin_);
00599
00600 return *this;
00601 }
00602
00603 template<class T>
00604 Vector<T>& Vector<T>::operator=(const T & value) {
00605 std::fill(begin_,end_,T(value));
00606
00607 return *this;
00608 }
00609
00610 template<class T>
00611 Vector<T> Vector<T>::operator+(const Vector<T>& v) const{
00612 if(sizeVector != v.sizeVector) throw MathException("incompatible vector size");
00613
00614 Vector tmp(sizeVector);
00615
00616 std::transform(begin_, end_, v.begin_, tmp.begin_, std::plus<T>());
00617
00618 return tmp;
00619 }
00620
00621
00622 template<class T>
00623 Vector<T> Vector<T>::operator-(const Vector<T>& v) const{
00624 if(sizeVector != v.sizeVector) throw MathException("incompatible vector size");
00625
00626 Vector tmp(sizeVector);
00627
00628 std::transform(begin_, end_, v.begin_, tmp.begin_, std::minus<T>());
00629
00630 return tmp;
00631 }
00632
00633 template<class T>
00634 T Vector<T>::operator*(const Vector<T>& v) const{
00635 if(sizeVector != v.sizeVector) throw MathException("incompatible vector size");
00636
00637 return std::inner_product(begin_, end_, v.begin_,T(0.0));
00638 }
00639
00640 template<class T>
00641 Vector<T>& Vector<T>::operator+=(const Vector<T>& v)
00642 {
00643 if(sizeVector != v.sizeVector) throw MathException("incompatible vector size");
00644
00645 std::transform(begin_, end_, v.begin_, begin_, std::plus<T>());
00646
00647 return *this;
00648 }
00649
00650 template<class T>
00651 Vector<T>& Vector<T>::operator-=(const Vector<T>& v){
00652 if(sizeVector != v.sizeVector) throw MathException("incompatible vector size");
00653
00654 std::transform(begin_, end_, v.begin_, begin_, std::minus<T>());
00655
00656 return *this;
00657 }
00658
00659 template<class T>
00660 Vector<T>& Vector<T>::operator/=(const T& d){
00661 std::transform(begin_, end_, begin_, std::bind2nd(std::divides<T>(), d));
00662
00663 return *this;
00664 }
00665
00666 template<class T>
00667 Vector<T>& Vector<T>::operator*=(const T& d){
00668 std::transform(begin_, end_, begin_, std::bind2nd(std::multiplies<T>(), d));
00669 return *this;
00670 }
00671
00672 template<class T>
00673 T& Vector<T>::operator[](const unsigned int& i){
00674 return data[i];
00675 }
00676
00677 template<class T>
00678 const T& Vector<T>::operator[](const unsigned int& i) const{
00679 return data[i];
00680 }
00681
00682 template<class T>
00683 T& Vector<T>::operator()(const unsigned int& i){
00684 return data[i];
00685 }
00686
00687 template<class T>
00688 const T& Vector<T>::operator()(const unsigned int& i) const{
00689 return data[i];
00690 }
00691
00692 template<class T>
00693 Vector<T> Vector<T>::operator^(const Vector<T>& v) const{
00694 if(sizeVector!= 3) throw MathException("(this) cross product only with vectors of size 3");
00695 if(v.sizeVector != 3) throw MathException("cross product only with vectors of size 3");
00696
00697 Vector<T> tmp(3);
00698 tmp[0] = data[1]*v[2] - data[2]*v[1];
00699 tmp[1] = data[2]*v[0] - data[0]*v[2];
00700 tmp[2] = data[0]*v[1] - data[1]*v[0];
00701
00702 return tmp;
00703 }
00704
00705
00706
00707 template<class T>
00708 void Vector<T>::roundZero(const double & d){
00709 T *iter = begin_;
00710
00711 while(iter != end_){
00712 if(std::fabs((double)(*iter)) < d) (*iter) = T(0.0);
00713 ++iter;
00714 }
00715 }
00716
00717
00718 template<class T>
00719 void Vector<T>::setSubVector(const unsigned int& index, const Vector<T>& v){
00720 if(index >= sizeVector) throw MathException("index is out of bounds");
00721 if(index + v.sizeVector > sizeVector) throw MathException("index is out of bounds(v.sizeVector is too big)");
00722 std::copy(v.begin_, v.end_, begin_ + index);
00723 }
00724
00725 template<class T>
00726 void Vector<T>::setSubVector(const unsigned int& index1, const unsigned int& index2,const unsigned int& size, const Vector<T>& v){
00727 if(index1 >= sizeVector) throw MathException("index1 is out of bounds");
00728 if(index1 + size > sizeVector) throw MathException("index1 is out of bounds(size is too big)");
00729 if(index2 >= v.sizeVector) throw MathException("index2 is out of bounds");
00730 if(index2 + size > v.sizeVector) throw MathException("index2 is out of bounds(size is too big)");
00731 std::copy(v.begin_+index2, v.begin_+index2+size, begin_ + index1);
00732 }
00733
00734 template<class T>
00735 Vector<T> Vector<T>::getSubVector(const unsigned int& index, const int& size) const{
00736 if(index >= sizeVector) throw MathException("index is out of bounds");
00737 if(index + size > sizeVector) throw MathException("index is out of bounds (size is too big)");
00738
00739 Vector<T> v(size);
00740 std::copy(begin_ + index, begin_ + index + size , v.begin_);
00741 return v;
00742 }
00743
00744 template<class T>
00745 double Vector<T>::getNorm(void) const{
00746 double squareSum = 0.0;
00747 for(unsigned int i=0;i<sizeVector;i++){
00748 squareSum += (double)(this->data[i]*this->data[i]);
00749 }
00750 return sqrt(squareSum);
00751 }
00752
00753 template<class T>
00754 Vector<T>& Vector<T>::normalize(void){
00755 double norm = getNorm();
00756 for(unsigned int i=0;i<sizeVector;i++){
00757 this->data[i] = T(this->data[i] / norm);
00758 }
00759 return *this;
00760 }
00761
00762 template<class T>
00763 Vector<T> Vector<T>::getNormalized(void) const{
00764 Vector<T> v(*this);
00765 v.normalize();
00766 return v;
00767 }
00768
00769
00770 template<class T>
00771 Vector<T> Vector<T>::getHomogeneous(const T &d) const{
00772 Vector<T> tmp(sizeVector+1);
00773
00774 std::copy(begin_, end_, tmp.begin_);
00775 tmp[sizeVector] = d;
00776
00777 return tmp;
00778 }
00779
00780
00781 template<class T>
00782 Vector<T> Vector<T>::getUnhomogeneous(const T &zeroValue) const{
00783 if(sizeVector == 1) return *this;
00784
00785 Vector<T> tmp(sizeVector-1);
00786
00787
00788 T value = this->data[sizeVector-1];
00789 if(std::fabs((float)value) > zeroValue && value != T(1.0))
00790 std::transform(begin_, end_-1, tmp.begin_, std::bind2nd(std::divides<T>(), value));
00791 else
00792 std::copy(begin_, end_-1, tmp.begin_);
00793
00794 return tmp;
00795 }
00796
00797
00798 template<class T>
00799 void Vector<T>::setHomogeneousNormalForm(const T &zeroValue) const{
00800 T value = this->data[sizeVector-1];
00801 if(std::fabs((float)value) > (float)zeroValue && value != T(1.0)){
00802 std::transform(begin_, end_-1, begin_, std::bind2nd(std::divides<T>(), value));
00803 this->data[sizeVector-1] = T(1.0);
00804 }
00805 }
00806
00807
00808 template<class T>
00809 void Vector<T>::swap(const unsigned int& index1,
00810 const unsigned int& index2){
00811 if(index1 >= sizeVector || index2 >= sizeVector) throw MathException("Index out of bounds");
00812
00813 std::swap(data[index1],data[index2]);
00814 }
00815
00822 template<class U>
00823 std::ostream& operator<< (std::ostream& stream,
00824 const Vector<U>& v){
00825 stream << "(";
00826 for (unsigned int i=0; i<v.size()-1; ++i)
00827 stream << v[i] << " , ";
00828
00829 stream << v[v.size()-1]<< ")";
00830
00831 return stream;
00832 }
00833
00840 template<class U>
00841 Vector<U> operator* (const U& d,
00842 const Vector<U>& v){
00843 return v*d;
00844 }
00845
00846
00847
00848
00849
00850 typedef Vector<float> Vectorf;
00851 typedef Vector<double> Vectord;
00852 typedef Vector<int> Vectori;
00853
00854
00855
00856
00857 }
00858
00859
00860
00861
00862 #endif