IMP logo
IMP Reference Guide  develop.eb1b99edaa,2026/06/22
The Integrative Modeling Platform
VectorD.h
Go to the documentation of this file.
1 /**
2  * \file IMP/VectorD.h \brief Simple D vector class.
3  *
4  * Copyright 2007-2026 IMP Inventors. All rights reserved.
5  *
6  */
7 
8 #ifndef IMPKERNEL_VECTOR_D_H
9 #define IMPKERNEL_VECTOR_D_H
10 
11 #include <IMP/kernel_config.h>
12 #include <IMP/internal/VectorBaseD.h>
13 #include <IMP/types.h>
14 #include <IMP/check_macros.h>
15 #include <IMP/exception.h>
16 #include <IMP/utility.h>
17 #include <IMP/InputAdaptor.h>
18 #include <IMP/random.h>
19 #include <IMP/vectord_macros.h>
20 #include <boost/random/variate_generator.hpp>
21 #include <boost/random/normal_distribution.hpp>
22 #include <boost/range.hpp>
23 
24 #include <limits>
25 #include <cmath>
26 #include <boost/random/normal_distribution.hpp>
27 
28 IMPKERNEL_BEGIN_NAMESPACE
29 //! A Cartesian vector in D-dimensions.
30 /** Store a vector of Cartesian coordinates. It supports all expected
31  mathematical operators, including using * for the dot product.
32  \see Vector3D
33  \see Vector2D
34 
35  \geometry
36  */
37 template <int D>
38 class VectorD : public internal::VectorBaseD<D> {
39  /* implementing it via a specialization is in order to get swig
40  to only use the right constructors as well as C++. */
41  IMP_VECTOR_METHODS(D);
42 };
43 
44 template <>
45 class VectorD<-1> : public internal::VectorBaseD<-1> {
46  std::vector<double> get_range(double x0, double x1, double x2, double x3,
47  double x4, double x5) {
48  IMP_USAGE_CHECK(x0 != std::numeric_limits<double>::max(),
49  "Bad init values");
50  std::vector<double> ret;
51  ret.push_back(x0);
52  if (x1 != std::numeric_limits<double>::max()) ret.push_back(x1);
53  if (x2 != std::numeric_limits<double>::max()) ret.push_back(x2);
54  if (x3 != std::numeric_limits<double>::max()) ret.push_back(x3);
55  if (x4 != std::numeric_limits<double>::max()) ret.push_back(x4);
56  if (x5 != std::numeric_limits<double>::max()) ret.push_back(x5);
57  return ret;
58  }
59 
60  public:
61  IMP_VECTOR_METHODS(-1);
62  explicit VectorD(double x0, double x1 = std::numeric_limits<double>::max(),
63  double x2 = std::numeric_limits<double>::max(),
64  double x3 = std::numeric_limits<double>::max(),
65  double x4 = std::numeric_limits<double>::max(),
66  double x5 = std::numeric_limits<double>::max())
67  : P(get_range(x0, x1, x2, x3, x4, x5)) {}
68 };
69 
70 template <>
71 class VectorD<1> : public internal::VectorBaseD<1> {
72  public:
73  IMP_VECTOR_METHODS(1);
74 
75  //! Initialize the 1-vector from its value.
76  VectorD(double x) { P::operator[](0) = x; }
77 };
78 template <>
79 class VectorD<2> : public internal::VectorBaseD<2> {
80  public:
81  IMP_VECTOR_METHODS(2);
82 
83  VectorD(double x, double y) {
84  P::operator[](0) = x;
85  P::operator[](1) = y;
86  }
87 };
88 template <>
89 class VectorD<3> : public internal::VectorBaseD<3> {
90  public:
91  IMP_VECTOR_METHODS(3);
92 
93  VectorD(double x, double y, double z) {
94  P::operator[](0) = x;
95  P::operator[](1) = y;
96  P::operator[](2) = z;
97  }
98 };
99 template <>
100 class VectorD<4> : public internal::VectorBaseD<4> {
101  public:
102  IMP_VECTOR_METHODS(4);
103 
104  VectorD(double x0, double x1, double x2, double x3) {
105  P::operator[](0) = x0;
106  P::operator[](1) = x1;
107  P::operator[](2) = x2;
108  P::operator[](3) = x3;
109  }
110 };
111 template <>
112 class VectorD<5> : public internal::VectorBaseD<5> {
113  public:
114  IMP_VECTOR_METHODS(5);
115 
116  VectorD(double x0, double x1, double x2, double x3, double x4) {
117  P::operator[](0) = x0;
118  P::operator[](1) = x1;
119  P::operator[](2) = x2;
120  P::operator[](3) = x3;
121  P::operator[](4) = x4;
122  }
123 };
124 template <>
125 class VectorD<6> : public internal::VectorBaseD<6> {
126  public:
127  IMP_VECTOR_METHODS(6);
128 
129  VectorD(double x0, double x1, double x2, double x3, double x4, double x5) {
130  P::operator[](0) = x0;
131  P::operator[](1) = x1;
132  P::operator[](2) = x2;
133  P::operator[](3) = x3;
134  P::operator[](4) = x4;
135  P::operator[](5) = x5;
136  }
137 };
138 
139 #ifndef IMP_DOXYGEN
140 
141 template <int D>
142 inline std::ostream &operator<<(std::ostream &out, const VectorD<D> &v) {
143  v.show(out);
144  return out;
145 }
146 
147 #ifndef SWIG
148 // SWIG 3.0.0 cannot parse operator>>
149 template <int D>
150 inline std::istream &operator>>(std::istream &in, VectorD<D> &v) {
151  for (unsigned int i = 0; i < D; ++i) {
152  in >> v[i];
153  }
154  return in;
155 }
156 #endif
157 
158 #endif
159 
160 //! lexicographic comparison of two vectors
161 /** Note that this is not very reliable and probably should not be used.
162  \see VectorD
163  */
164 template <int D>
165 inline int compare(const VectorD<D> &a, const VectorD<D> &b) {
166  IMP_USAGE_CHECK(a.get_dimension() == b.get_dimension(),
167  "Dimensions don't match.");
168  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
169  if (a[i] < b[i])
170  return -1;
171  else if (a[i] > b[i])
172  return 1;
173  }
174  return 0;
175 }
176 
177 /** \see VectorD */
178 template <int D>
179 inline VectorD<D> operator*(double s, VectorD<D> o) {
180  return o *= s;
181 }
182 
183 //! Compute the squared distance between two vectors
184 /** \see VectorD
185  */
186 template <int D>
187 inline double get_squared_distance(const VectorD<D> &v1, const VectorD<D> &v2) {
188  return (v1 - v2).get_squared_magnitude();
189 }
190 
191 //! Compute the distance between two vectors
192 /** \see VectorD
193  */
194 template <int D>
195 inline double get_distance(const VectorD<D> &v1, const VectorD<D> &v2) {
196  return std::sqrt(get_squared_distance(v1, v2));
197 }
198 
199 //! Return the basis vector for the given coordinate
200 /** Return the unit vector pointing in the direction of the requested
201  coordinate. That is
202  \code
203  get_basis_vector_d<3>(2)== Vector3D(0,0,1);
204  \endcode
205  \see VectorD
206  */
207 template <int D>
208 inline VectorD<D> get_basis_vector_d(unsigned int coordinate) {
209  IMP_USAGE_CHECK(coordinate < D, "There are only " << D << " basis vectors");
210  double vs[D];
211  for (unsigned int i = 0; i < D; ++i) {
212  if (i == coordinate)
213  vs[i] = 1;
214  else
215  vs[i] = 0;
216  }
217  return VectorD<D>(vs, vs + D);
218 }
219 
220 //! Return the basis vector for the given coordinate
221 template <int D>
222 inline VectorD<D> get_basis_vector_kd(int Di, unsigned int coordinate) {
223  IMP_USAGE_CHECK(D == Di, "D must be equal");
224  IMP_UNUSED(Di);
225  return get_basis_vector_d<D>(coordinate);
226 }
227 
228 //! Return a dynamically sized basis vector
229 template <>
230 inline VectorD<-1> get_basis_vector_kd(int D, unsigned int coordinate) {
231  IMP_USAGE_CHECK(D > 0, "D must be positive");
232  IMP_USAGE_CHECK(coordinate < static_cast<unsigned int>(D),
233  "There are only " << D << " basis vectors");
234  boost::scoped_array<double> vs(new double[D]);
235  for (int i = 0; i < D; ++i) {
236  if (i == static_cast<int>(coordinate))
237  vs[i] = 1;
238  else
239  vs[i] = 0;
240  }
241  return VectorD<-1>(vs.get(), vs.get() + D);
242 }
243 
244 //! Return a dynamically sized basis vector
245 inline VectorD<-1> get_basis_vector_kd(int D, unsigned int coordinate) {
246  return get_basis_vector_kd<-1>(D, coordinate);
247 }
248 
249 //! Return a vector of zeros
250 template <int D>
252  IMP_USAGE_CHECK(D > 0, "D must be positive");
253  VectorD<D> ret;
254  for (int i = 0; i < D; ++i) {
255  ret[i] = 0;
256  }
257  return ret;
258 }
259 
260 //! Return a dynamically sized vector of zeros
261 template <int D>
263  IMP_USAGE_CHECK(D == Di, "D must be equal");
264  IMP_UNUSED(Di);
265  return get_zero_vector_d<D>();
266 }
267 
268 //! Return a dynamically sized vector of zeros
269 template<>
270 inline VectorD<-1> get_zero_vector_kd(int D) {
271  IMP_USAGE_CHECK(D > 0, "D must be positive");
272  Floats vs(D, 0);
273  return VectorD<-1>(vs.begin(), vs.end());
274 }
275 
276 //! Return a dynamically sized vector of zeros
277 inline VectorD<-1> get_zero_vector_kd(int D) {
278  return get_zero_vector_kd<-1>(D);
279 }
280 
281 //! Return a vector of ones (or another constant)
282 template <int D>
283 inline VectorD<D> get_ones_vector_d(double v = 1) {
284  IMP_USAGE_CHECK(D > 0, "D must be positive");
285  VectorD<D> ret;
286  for (unsigned int i = 0; i < D; ++i) {
287  ret[i] = v;
288  }
289  return ret;
290 }
291 
292 //! Return a vector of ones (or another constant)
293 /** Di must equal D. */
294 template <int D>
295 inline VectorD<D> get_ones_vector_kd(unsigned int Di, double v = 1) {
296  IMP_USAGE_CHECK(D == Di, "D must be equal");
297  IMP_UNUSED(Di);
298  return get_ones_vector_d<D>(v);
299 }
300 
301 //! Return a vector of ones (or another constant)
302 template <>
303 inline VectorD<-1> get_ones_vector_kd(unsigned int D, double v) {
304  IMP_USAGE_CHECK(D > 0, "D must be positive");
305  boost::scoped_array<double> vv(new double[D]);
306  for (unsigned int i = 0; i < D; ++i) {
307  vv[i] = v;
308  }
309  return VectorD<-1>(vv.get(), vv.get() + D);
310 }
311 
312 //! Return a dynamically sized vector of zeros
313 inline VectorD<-1> get_ones_vector_kd(unsigned int D, double v = 1) {
314  return get_ones_vector_kd<-1>(D, v);
315 }
316 
317 #ifndef SWIG
318 
319 /** \name Norms
320  We define a number of standard, \f$L^p\f$, norms on VectorD.
321  - \f$L^1\f$ is the Manhattan distance, the sum of the components
322  - \f$L^2\f$ is the standard Euclidean length
323  - \f$L^{\inf}\f$ is the maximum of the components
324  @{
325 */
326 
327 template <int D>
328 inline double get_l2_norm(const VectorD<D> &v) {
329  return v.get_magnitude();
330 }
331 
332 template <int D>
333 inline double get_l1_norm(const VectorD<D> &v) {
334  double n = std::abs(v[0]);
335  for (unsigned int i = 1; i < v.get_dimension(); ++i) {
336  n += std::abs(v[i]);
337  }
338  return n;
339 }
340 
341 template <int D>
342 inline double get_linf_norm(const VectorD<D> &v) {
343  double n = std::abs(v[0]);
344  for (unsigned int i = 1; i < v.get_dimension(); ++i) {
345  n = std::max(n, std::abs(v[i]));
346  }
347  return n;
348 }
349 
350 /** @} */
351 
352 #ifndef IMP_DOXYGEN
353 
354 template <int D>
355 struct SpacesIO {
356  const VectorD<D> &v_;
357  SpacesIO(const VectorD<D> &v) : v_(v) {}
358 };
359 
360 template <int D>
361 struct CommasIO {
362  const VectorD<D> &v_;
363  CommasIO(const VectorD<D> &v) : v_(v) {}
364 };
365 template <int D>
366 inline std::ostream &operator<<(std::ostream &out, const SpacesIO<D> &s) {
367  s.v_.show(out, " ", false);
368  return out;
369 }
370 template <int D>
371 inline std::ostream &operator<<(std::ostream &out, const CommasIO<D> &s) {
372  s.v_.show(out, ", ", false);
373  return out;
374 }
375 
376 //! Use this before outputting to delimited vector entries with a space
377 /** std::cout << spaces_io(v);
378  produces "1.0 2.0 3.0"
379  \see VectorD
380  */
381 template <int D>
382 inline SpacesIO<D> spaces_io(const VectorD<D> &v) {
383  return SpacesIO<D>(v);
384 }
385 
386 //! Use this before outputting to delimited vector entries with a comma
387 /** std::cout << commas_io(v);
388  produces "1.0, 2.0, 3.0"
389  \see VectorD
390  */
391 template <int D>
392 inline CommasIO<D> commas_io(const VectorD<D> &v) {
393  return CommasIO<D>(v);
394 }
395 #endif // doxygen
396 
397 #endif // swig
398 /** 1D vector typedef for swig */
400 /** 1D vectors typedef for swig */
402 /** 2D vector typedef for swig */
404 /** 2D vectors typedef for swig */
406 /** 3D vector typedef for swig */
408 /** 3D vectors typedef for swig */
410 /** 4D vector typedef for swig */
412 /** 4D vectors typedef for swig */
414 /** 5D vector typedef for swig */
416 /** 5D vectors typedef for swig */
418 /** 6D vector typedef for swig */
420 /** 6D vector typedef for swig */
422 /** KD vector typedef for swig */
423 typedef VectorD<-1> VectorKD;
424 /** KD vectors typedef for swig */
425 typedef Vector<VectorD<-1> > VectorKDs;
426 
427 #ifndef SWIG
428 /** \see VectorD \genericgeometry */
429 template <class C>
430 inline const VectorD<C::DIMENSION> &get_vector_geometry(const C &g) {
431  return g;
432 }
433 /** \see VectorD \genericgeometry */
434 template <class C, class E>
435 inline void set_vector_geometry(C &g, const E &v) {
436  g = v;
437 }
438 #endif
439 
440 //! Return the vector that is the elementwise product of the two.
441 /** \see VectorD */
442 template <int D>
444  const VectorD<D> &b) {
445  VectorD<D> ret(a);
446  for (unsigned int i = 0; i < ret.get_dimension(); ++i) {
447  ret[i] *= b[i];
448  }
449  return ret;
450 }
451 
452 //! Return the vector that is the elementwise product of the two.
453 /** \see VectorD */
454 template <int D>
456  const VectorD<D> &b) {
457  IMP_USAGE_CHECK(a.size() == b.get_dimension(), "Dimensions don't match,");
458  VectorD<D> ret(b);
459  for (unsigned int i = 0; i < ret.get_dimension(); ++i) {
460  ret[i] *= a[i];
461  }
462  return ret;
463 }
464 
465 IMPKERNEL_END_NAMESPACE
466 
467 /* Overload std::get to work on VectorD similarly to std::array */
468 namespace std {
469  template <unsigned int I, int D>
470  const double& get(const IMP::VectorD<D> &v) {
471  static_assert(D > 0, "std::get does not work for VectorKD");
472  static_assert(I < D, "vector index is within bounds");
473  return *(v.begin() + I);
474  }
475 
476  template <unsigned int I, int D>
477  double& get(IMP::VectorD<D> &v) {
478  static_assert(D > 0, "std::get does not work for VectorKD");
479  static_assert(I < D, "vector index is within bounds");
480  return *(v.begin() + I);
481  }
482 }
483 
484 #endif /* IMPKERNEL_VECTOR_D_H */
Basic types used by IMP.
A Cartesian vector in D-dimensions.
Definition: VectorD.h:38
VectorD< D > get_elementwise_product(const Ints &a, const VectorD< D > &b)
Return the vector that is the elementwise product of the two.
Definition: VectorD.h:455
VectorD< 2 > Vector2D
Definition: VectorD.h:403
Vector< VectorD< 6 > > Vector6Ds
Definition: VectorD.h:421
VectorD< D > get_zero_vector_d()
Return a vector of zeros.
Definition: VectorD.h:251
VectorD< 1 > Vector1D
Definition: VectorD.h:399
VectorD< 6 > Vector6D
Definition: VectorD.h:419
VectorD<-1 > get_ones_vector_kd(unsigned int D, double v)
Return a vector of ones (or another constant)
Definition: VectorD.h:303
VectorD< 5 > Vector5D
Definition: VectorD.h:415
VectorD< 4 > Vector4D
Definition: VectorD.h:411
Exception definitions and assertions.
VectorD< D > operator*(double s, VectorD< D > o)
Definition: VectorD.h:179
Vector< VectorD< 5 > > Vector5Ds
Definition: VectorD.h:417
VectorD<-1 > get_zero_vector_kd(int D)
Return a dynamically sized vector of zeros.
Definition: VectorD.h:270
Convenience class to accept multiple input types.
Vector< VectorD<-1 > > VectorKDs
Definition: VectorD.h:425
VectorD< 3 > Vector3D
Definition: VectorD.h:407
#define IMP_UNUSED(variable)
void set_vector_geometry(C &g, const E &v)
Definition: VectorD.h:435
VectorD< D > get_ones_vector_d(double v=1)
Return a vector of ones (or another constant)
Definition: VectorD.h:283
double get_squared_distance(const VectorD< D > &v1, const VectorD< D > &v2)
Compute the squared distance between two vectors.
Definition: VectorD.h:187
double get_distance(const VectorD< D > &v1, const VectorD< D > &v2)
Compute the distance between two vectors.
Definition: VectorD.h:195
Vector< VectorD< 2 > > Vector2Ds
Definition: VectorD.h:405
Various general useful functions for IMP.
int compare(const VectorD< D > &a, const VectorD< D > &b)
lexicographic comparison of two vectors
Definition: VectorD.h:165
Vector< VectorD< 3 > > Vector3Ds
Definition: VectorD.h:409
const VectorD< C::DIMENSION > & get_vector_geometry(const C &g)
Definition: VectorD.h:430
VectorD<-1 > VectorKD
Definition: VectorD.h:423
Helper macros for throwing and handling exceptions.
Various helper macros for the VectorD class.
VectorD<-1 > get_basis_vector_kd(int D, unsigned int coordinate)
Return a dynamically sized basis vector.
Definition: VectorD.h:230
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
Random number generators used by IMP.
VectorD< D > get_basis_vector_d(unsigned int coordinate)
Return the basis vector for the given coordinate.
Definition: VectorD.h:208
Vector< VectorD< 4 > > Vector4Ds
Definition: VectorD.h:413
Vector< VectorD< 1 > > Vector1Ds
Definition: VectorD.h:401