8 #ifndef IMPALGEBRA_VECTOR_D_H
9 #define IMPALGEBRA_VECTOR_D_H
11 #include <IMP/algebra/algebra_config.h>
19 #include "internal/vector.h"
23 #include <boost/random/normal_distribution.hpp>
24 #include <boost/static_assert.hpp>
26 #if IMP_HAS_CHECKS >= IMP_USAGE
27 #define IMP_VECTOR_CHECK check_vector()
28 #define IMP_VECTOR_CHECK_INDEX(i) check_index(i)
29 #define IMP_VECTOR_CHECK_COMPATIBLE(o) \
30 check_compatible_vector(o); o.check_vector()
32 #define IMP_VECTOR_CHECK
33 #define IMP_VECTOR_CHECK_INDEX(i)
34 #define IMP_VECTOR_CHECK_COMPATIBLE(o)
38 IMPALGEBRA_BEGIN_NAMESPACE
50 void check_vector()
const {
52 "Attempt to use uninitialized vector.");
55 void check_compatible_vector(
const VectorD<OD> &o)
const {
58 "Dimensions don't match: "
59 << get_dimension() <<
" vs "
60 << o.get_dimension());
62 void check_index(
unsigned int i)
const {
63 #if IMP_HAS_CHECKS < IMP_INTERNAL
67 "Invalid component of vector requested: "
68 << i <<
" of " <<get_dimension());
71 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
74 BOOST_STATIC_ASSERT(D==-1 || OD==-1 || D==OD);
76 || o.get_dimension() ==
static_cast<unsigned int>(D),
77 "Dimensions don't match in conversion");
78 data_.set_coordinates(o.coordinates_begin(),
83 BOOST_STATIC_ASSERT(D==-1 || OD==-1 || D==OD);
85 "Dimensions don't match in conversion");
86 data_.set_coordinates(o.coordinates_begin(),
93 if (D!=-1 && static_cast<int>(f.size()) != D) {
94 IMP_THROW(
"Expected " << D <<
" but got " << f.size(),
97 data_.set_coordinates(f.begin(), f.end());
104 data_.set_coordinates(b,e);
112 #if defined(IMP_SWIG_WRAPPER) || defined(_MSC_VER)
114 "Need " << D <<
" to construct a "
117 BOOST_STATIC_ASSERT(D==1);
119 data_.set_coordinates(&x, &x+1);
124 #if defined(IMP_SWIG_WRAPPER) || defined(_MSC_VER)
128 BOOST_STATIC_ASSERT(D==2);
131 data_.set_coordinates(d, d+2);
136 #ifdef IMP_SWIG_WRAPPER
140 BOOST_STATIC_ASSERT(D==3);
143 data_.set_coordinates(d, d+3);
147 VectorD(
double x0,
double x1,
double x2,
double x3) {
148 #if defined(IMP_SWIG_WRAPPER) || defined(_MSC_VER)
152 BOOST_STATIC_ASSERT(D==4);
154 double d[]={x0, x1, x2, x3};
155 data_.set_coordinates(d, d+4);
165 IMP_VECTOR_CHECK_INDEX(i);
167 return data_.get_data()[i];
172 IMP_VECTOR_CHECK_INDEX(i);
173 return data_.get_data()[i];
176 double get_scalar_product(
const VectorD<D> &o)
const {
177 IMP_VECTOR_CHECK_COMPATIBLE(o);
180 for (
unsigned int i=0; i< get_dimension(); ++i) {
181 ret += operator[](i)* o.operator[](i);
186 double get_squared_magnitude()
const {
187 return get_scalar_product(*
this);
190 double get_magnitude()
const {
191 return std::sqrt(get_squared_magnitude());
202 const double tiny_double = 1e-12;
203 double mag = get_magnitude();
204 if(mag > tiny_double){
205 return operator/(mag) ;
211 Floats rand_v(get_dimension());
212 boost::variate_generator<boost::rand48, boost::normal_distribution<> >
214 ::boost::normal_distribution<>(0,1.0) );
215 for (
unsigned int i=0; i< get_dimension(); ++i) {
216 rand_v[i] = generator();
224 IMP_VECTOR_CHECK_COMPATIBLE(o);
225 return get_scalar_product(o);
228 VectorD operator*(
double s)
const {
235 VectorD operator/(
double s)
const {
242 VectorD operator-()
const {
245 for (
unsigned int i=0; i<get_dimension(); ++i) {
251 VectorD operator-(
const VectorD &o)
const {
252 IMP_VECTOR_CHECK_COMPATIBLE(o);
259 VectorD operator+(
const VectorD &o)
const {
260 IMP_VECTOR_CHECK_COMPATIBLE(o);
267 VectorD& operator+=(
const VectorD &o) {
268 IMP_VECTOR_CHECK_COMPATIBLE(o);
270 for (
unsigned int i=0; i<get_dimension(); ++i) {
271 operator[](i) += o[i];
276 VectorD& operator-=(
const VectorD &o) {
277 IMP_VECTOR_CHECK_COMPATIBLE(o);
279 for (
unsigned int i=0; i<get_dimension(); ++i) {
280 operator[](i) -= o[i];
285 VectorD& operator/=(
double f) {
287 for (
unsigned int i=0; i<get_dimension(); ++i) {
293 VectorD& operator*=(
double f) {
295 for (
unsigned int i=0; i<get_dimension(); ++i) {
301 void show(std::ostream &out, std::string delim,
302 bool parens=
true)
const {
304 if (parens) out <<
"(";
305 for (
unsigned int i=0; i<get_dimension(); ++i) {
306 out << operator[](i);
307 if (i != get_dimension()-1) {
311 if (parens) out <<
")";
317 typedef double* CoordinateIterator;
318 CoordinateIterator coordinates_begin() {
return data_.get_data();}
319 CoordinateIterator coordinates_end() {
320 return data_.get_data()+get_dimension();
322 typedef const double* CoordinateConstIterator;
323 CoordinateConstIterator coordinates_begin()
const {
324 return data_.get_data();
326 CoordinateConstIterator coordinates_end()
const {
327 return data_.get_data()+get_dimension();
334 Floats get_coordinates()
const {
335 return Floats(coordinates_begin(), coordinates_end());
339 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
340 const double *get_data()
const {
return data_.get_data();}
342 unsigned int get_dimension()
const {
343 return data_.get_dimension();
347 internal::VectorData<double, D, false> data_;
354 inline std::ostream &operator<<(std::ostream &out, const VectorD<D> &v) {
360 inline std::istream &operator>>(std::istream &in, VectorD<D> &v) {
361 for (
unsigned int i=0; i< D; ++i) {
376 "Dimensions don't match.");
377 for (
unsigned int i=0; i< a.get_dimension(); ++i) {
378 if (a[i] < b[i])
return -1;
379 else if (a[i] > b[i])
return 1;
395 return (v1-v2).get_squared_magnitude();
416 IMP_USAGE_CHECK(coordinate<D,
"There are only " << D <<
" basis vectors");
418 for (
unsigned int i=0; i< D; ++i) {
419 if (i==coordinate) vs[i]=1;
427 unsigned int coordinate) {
430 "There are only " << D <<
" basis vectors");
431 boost::scoped_array<double> vs(
new double[D]);
432 for (
int i=0; i< D; ++i) {
433 if (i==static_cast<int>(coordinate)) vs[i]=1;
436 return VectorD<-1>(vs.get(), vs.get()+D);
451 return VectorD<-1>(vs.begin(), vs.end());
458 boost::scoped_array<double> vv(
new double[D]);
459 for (
unsigned int i=0; i< D; ++i) {
462 return VectorD<-1>(vv.get(), vv.get()+D);
469 boost::scoped_array<double> vv(
new double[D]);
470 for (
unsigned int i=0; i< D; ++i) {
488 inline double get_l2_norm(
const VectorD<D> &v) {
489 return v.get_magnitude();
493 inline double get_l1_norm(
const VectorD<D> &v) {
494 double n=std::abs(v[0]);
495 for (
unsigned int i=1; i< v.get_dimension(); ++i) {
502 inline double get_linf_norm(
const VectorD<D> &v) {
503 double n=std::abs(v[0]);
504 for (
unsigned int i=1; i< v.get_dimension(); ++i) {
505 n= std::max(n, std::abs(v[i]));
517 const VectorD<D> &v_;
518 SpacesIO(
const VectorD<D> &v): v_(v){}
524 const VectorD<D> &v_;
525 CommasIO(
const VectorD<D> &v): v_(v){}
528 inline std::ostream &operator<<(std::ostream &out, const SpacesIO<D> &s)
530 s.v_.show(out,
" ",
false);
534 inline std::ostream &operator<<(std::ostream &out, const CommasIO<D> &s)
536 s.v_.show(out,
", ",
false);
546 inline SpacesIO<D> spaces_io(
const VectorD<D> &v) {
547 return SpacesIO<D>(v);
559 inline CommasIO<D> commas_io(
const VectorD<D> &v) {
560 return CommasIO<D>(v);
610 for (
unsigned int i=0; i< ret.get_dimension(); ++i) {
623 "Dimensions don't match,");
625 for (
unsigned int i=0; i< ret.get_dimension(); ++i) {
690 IMPALGEBRA_END_NAMESPACE