00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMPALGEBRA_VECTOR_D_H
00009 #define IMPALGEBRA_VECTOR_D_H
00010
00011 #include "algebra_config.h"
00012 #include <IMP/macros.h>
00013 #include <IMP/exception.h>
00014 #include <IMP/utility.h>
00015 #include <boost/static_assert.hpp>
00016
00017 #include <vector>
00018 #include <limits>
00019 #include <cmath>
00020
00021 IMPALGEBRA_BEGIN_NAMESPACE
00022
00023
00024
00025
00026
00027
00028
00029
00030 template <unsigned int D>
00031 class VectorD
00032 {
00033 void check_vector() const {
00034 for (unsigned int i=0; i< D; ++i) {
00035 IMP_USAGE_CHECK(!is_nan(vec_[i]),
00036 "Attempt to use uninitialized vector.");
00037 }
00038 }
00039 public:
00040
00041 #ifndef IMP_DOXYGEN
00042 typedef VectorD<D> This;
00043 #endif
00044
00045
00046 template <class It>
00047 VectorD(It b, It e) {
00048 IMP_INTERNAL_CHECK(std::distance(b,e) == D,
00049 "The size of the range must match the dimension");
00050 std::copy(b,e, vec_);
00051 }
00052
00053
00054 explicit VectorD(double x) {
00055
00056
00057
00058 #if defined(IMP_SWIG_WRAPPER) || defined(_MSC_VER)
00059 IMP_USAGE_CHECK(D==1, "Need " << D << " to construct a "
00060 << D << "-vector.");
00061 #else
00062 BOOST_STATIC_ASSERT(D==1);
00063 #endif
00064 vec_[0] = x;
00065 }
00066
00067
00068 VectorD(double x, double y) {
00069 #if defined(IMP_SWIG_WRAPPER) || defined(_MSC_VER)
00070 IMP_USAGE_CHECK(D==2, "Need " << D << " to construct a "
00071 << D << "-vector.");
00072 #else
00073 BOOST_STATIC_ASSERT(D==2);
00074 #endif
00075 vec_[0] = x;
00076 vec_[1] = y;
00077 }
00078
00079
00080 VectorD(double x, double y, double z) {
00081 #ifdef IMP_SWIG_WRAPPER
00082 IMP_USAGE_CHECK(D==3, "Need " << D << " to construct a "
00083 << D << "-vector.");
00084 #else
00085 BOOST_STATIC_ASSERT(D==3);
00086 #endif
00087 vec_[0] = x;
00088 vec_[1] = y;
00089 vec_[2] = z;
00090 }
00091
00092
00093 VectorD(double x0, double x1, double x2, double x3) {
00094 #if defined(IMP_SWIG_WRAPPER) || defined(_MSC_VER)
00095 IMP_USAGE_CHECK(D==4, "Need " << D << " to construct a "
00096 << D << "-vector.");
00097 #else
00098 BOOST_STATIC_ASSERT(D==4);
00099 #endif
00100 vec_[0] = x0;
00101 vec_[1] = x1;
00102 vec_[2] = x2;
00103 if (D==4) {
00104
00105 vec_[3] = x3;
00106 }
00107 }
00108
00109
00110 VectorD() {
00111 #if IMP_BUILD < IMP_FAST
00112 for (unsigned int i=0; i< D; ++i) {
00113 vec_[i]= std::numeric_limits<double>::quiet_NaN();
00114 }
00115 #endif
00116 }
00117
00118
00119 double operator[](unsigned int i) const {
00120 IMP_INTERNAL_CHECK(i < D, "Invalid component of vector requested: "
00121 << i << " of " << D);
00122 check_vector();
00123 return vec_[i];
00124 }
00125
00126
00127 double& operator[](unsigned int i) {
00128 IMP_INTERNAL_CHECK(i < D, "Invalid component of vector requested: "
00129 << i << " of " << D);
00130 return vec_[i];
00131 }
00132
00133 double get_scalar_product(const VectorD<D> &o) const {
00134 check_vector();
00135 double ret=0;
00136 for (unsigned int i=0; i< D; ++i) {
00137 ret += vec_[i]* o.vec_[i];
00138 }
00139 return ret;
00140 }
00141
00142 double get_squared_magnitude() const {
00143 return get_scalar_product(*this);
00144 }
00145
00146 double get_magnitude() const {
00147 return std::sqrt(get_squared_magnitude());
00148 }
00149
00150 VectorD get_unit_vector() const {
00151 double mag = get_magnitude();
00152
00153 mag = std::max(mag, static_cast<double>(1e-12));
00154 return operator/(mag);
00155 }
00156 #ifndef IMP_DOXYGEN
00157 double operator*(const VectorD<D> &o) const {
00158 return get_scalar_product(o);
00159 }
00160
00161 VectorD operator*(double s) const {
00162 check_vector();
00163 This ret;
00164 for (unsigned int i=0; i< D; ++i) {
00165 ret.vec_[i] = vec_[i] * s;
00166 }
00167 return ret;
00168 }
00169
00170 VectorD operator/(double s) const {
00171 check_vector();
00172 This ret;
00173 for (unsigned int i=0; i< D; ++i) {
00174 ret.vec_[i] = vec_[i] / s;
00175 }
00176 return ret;
00177 }
00178
00179 VectorD operator-() const {
00180 check_vector();
00181 This ret;
00182 for (unsigned int i=0; i< D; ++i) {
00183 ret.vec_[i] = -vec_[i];
00184 }
00185 return ret;
00186 }
00187
00188 VectorD operator-(const VectorD &o) const {
00189 check_vector(); o.check_vector();
00190 This ret;
00191 for (unsigned int i=0; i< D; ++i) {
00192 ret.vec_[i] = vec_[i] - o.vec_[i];
00193 }
00194 return ret;
00195 }
00196
00197 VectorD operator+(const VectorD &o) const {
00198 check_vector(); o.check_vector();
00199 This ret;
00200 for (unsigned int i=0; i< D; ++i) {
00201 ret.vec_[i] = vec_[i] + o.vec_[i];
00202 }
00203 return ret;
00204 }
00205
00206 VectorD& operator+=(const VectorD &o) {
00207 check_vector(); o.check_vector();
00208 for (unsigned int i=0; i< D; ++i) {
00209 vec_[i] += o[i];
00210 }
00211 return *this;
00212 }
00213
00214 VectorD& operator-=(const VectorD &o) {
00215 check_vector(); o.check_vector();
00216 for (unsigned int i=0; i< D; ++i) {
00217 vec_[i] -= o[i];
00218 }
00219 return *this;
00220 }
00221
00222 VectorD& operator/=(double f) {
00223 check_vector();
00224 for (unsigned int i=0; i< D; ++i) {
00225 vec_[i] /= f;
00226 }
00227 return *this;
00228 }
00229
00230 VectorD& operator*=(double f) {
00231 check_vector();
00232 for (unsigned int i=0; i< D; ++i) {
00233 vec_[i] *= f;
00234 }
00235 return *this;
00236 }
00237
00238 void show(std::ostream &out=std::cout, std::string delim=", ",
00239 bool parens=true) const {
00240 check_vector();
00241 if (parens) out << "(";
00242 for (unsigned int i=0; i< D; ++i) {
00243 out << vec_[i];
00244 if (i != D-1) {
00245 out << delim;
00246 }
00247 }
00248 if (parens) out << ")";
00249 }
00250
00251 std::string __str__() const {
00252 std::ostringstream oss;
00253 show(oss);
00254 return oss.str();
00255 }
00256 #endif
00257
00258 typedef double* CoordinateIterator;
00259 CoordinateIterator coordinates_begin() {return vec_;}
00260 CoordinateIterator coordinates_end() {return vec_+D;}
00261 #ifndef SWIG
00262 typedef const double* CoordinateConstIterator;
00263 CoordinateConstIterator coordinates_begin() const {return vec_;}
00264 CoordinateConstIterator coordinates_end() const {return vec_+D;}
00265 #endif
00266
00267 #ifndef IMP_DOXYGEN
00268 const double *get_data() const {return vec_;}
00269 #endif
00270 private:
00271
00272 double vec_[D];
00273 };
00274
00275 #ifndef IMP_DOXYGEN
00276
00277 template <unsigned int D>
00278 std::ostream &operator<<(std::ostream &out, const VectorD<D> &v) {
00279 v.show(out);
00280 return out;
00281 }
00282
00283 template <unsigned int D>
00284 std::istream &operator>>(std::istream &in, VectorD<D> &v) {
00285 for (unsigned int i=0; i< D; ++i) {
00286 in >> v[i];
00287 }
00288 return in;
00289 }
00290
00291 #endif
00292
00293
00294
00295
00296 template <unsigned int D>
00297 int compare(const VectorD<D> &a, const VectorD<D> &b) {
00298 for (unsigned int i=0; i< D; ++i) {
00299 if (a[i] < b[i]) return -1;
00300 else if (a[i] > b[i]) return 1;
00301 }
00302 return 0;
00303 }
00304
00305
00306 template <unsigned int D>
00307 inline VectorD<D> operator*(double s, const VectorD<D> &o) {
00308 return o*s;
00309 }
00310
00311
00312
00313
00314 template <unsigned int D>
00315 double get_squared_distance(const VectorD<D> &v1, const VectorD<D> &v2) {
00316 double d, s = 0;
00317 for (unsigned int i=0; i< D; ++i) {
00318 d = v1[i] - v2[i];
00319 s += d*d;
00320 }
00321 return s;
00322 }
00323
00324
00325
00326
00327 template <unsigned int D>
00328 double get_distance(const VectorD<D> &v1, const VectorD<D> &v2) {
00329 return std::sqrt(get_squared_distance(v1, v2));
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 template <unsigned int D>
00341 VectorD<D> get_basis_vector_d(unsigned int coordinate) {
00342 IMP_USAGE_CHECK(coordinate<D, "There are only " << D << " basis vectors");
00343 double vs[D];
00344 for (unsigned int i=0; i< D; ++i) {
00345 if (i==coordinate) vs[i]=1;
00346 else vs[i]=0;
00347 }
00348 return VectorD<D>(vs, vs+D);
00349 }
00350
00351
00352 template <unsigned int D>
00353 VectorD<D> get_zero_vector_d() {
00354 double vs[D]={0};
00355 return VectorD<D>(vs, vs+D);
00356 }
00357
00358
00359
00360 template <unsigned int D>
00361 VectorD<D> get_ones_vector_d(double v=1) {
00362 VectorD<D> vv;
00363 for (unsigned int i=0; i< D; ++i) {
00364 vv[i]=v;
00365 }
00366 return vv;
00367 }
00368
00369
00370 #ifndef SWIG
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 template <unsigned int D>
00381 double get_l2_norm(const VectorD<D> &v) {
00382 return v.get_magnitude();
00383 }
00384
00385 template <unsigned int D>
00386 double get_l1_norm(const VectorD<D> &v) {
00387 double n=std::abs(v[0]);
00388 for (unsigned int i=1; i< D; ++i) {
00389 n+= std::abs(v[i]);
00390 }
00391 return n;
00392 }
00393
00394 template <unsigned int D>
00395 double get_linf_norm(const VectorD<D> &v) {
00396 double n=std::abs(v[0]);
00397 for (unsigned int i=1; i< D; ++i) {
00398 n= std::max(n, std::abs(v[i]));
00399 }
00400 return n;
00401 }
00402
00403
00404
00405 #ifndef IMP_DOXYGEN
00406
00407 template <unsigned int D>
00408 struct SpacesIO
00409 {
00410 const VectorD<D> &v_;
00411 SpacesIO(const VectorD<D> &v): v_(v){}
00412 };
00413
00414 template <unsigned int D>
00415 struct CommasIO
00416 {
00417 const VectorD<D> &v_;
00418 CommasIO(const VectorD<D> &v): v_(v){}
00419 };
00420 template <unsigned int D>
00421 inline std::ostream &operator<<(std::ostream &out, const SpacesIO<D> &s)
00422 {
00423 s.v_.show(out, " ", false);
00424 return out;
00425 }
00426 template <unsigned int D>
00427 inline std::ostream &operator<<(std::ostream &out, const CommasIO<D> &s)
00428 {
00429 s.v_.show(out, ", ", false);
00430 return out;
00431 }
00432
00433
00434
00435
00436
00437
00438 template <unsigned int D>
00439 SpacesIO<D> spaces_io(const VectorD<D> &v) {
00440 return SpacesIO<D>(v);
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 template <unsigned int D>
00452 CommasIO<D> commas_io(const VectorD<D> &v) {
00453 return CommasIO<D>(v);
00454 }
00455 #endif // doxygen
00456
00457 typedef VectorD<2> Vector2D;
00458 typedef std::vector<VectorD<2> > Vector2Ds;
00459 typedef VectorD<3> Vector3D;
00460 typedef std::vector<VectorD<3> > Vector3Ds;
00461 typedef VectorD<4> Vector4D;
00462 typedef std::vector<VectorD<4> > Vector4Ds;
00463 #endif //swig
00464
00465 IMPALGEBRA_END_NAMESPACE
00466
00467 #endif