/** * @file Vector.cpp * @brief typedef and functions to augment Boost's ublas::vector * @author Kai Ni * @author Frank Dellaert */ #include #include #include #include #include #include #include #include #ifdef WIN32 #include #endif #ifdef GSL #include // needed for gsl blas #include #endif #include #include #include "Vector.h" using namespace std; namespace gtsam { void odprintf(const char *format, ...) { char buf[4096], *p = buf; int n; va_list args; va_start(args, format); #ifdef WIN32 n = _vsnprintf(p, sizeof buf - 3, format, args); // buf-3 is room for CR/LF/NUL #else n = vsnprintf(p, sizeof buf - 3, format, args); // buf-3 is room for CR/LF/NUL #endif va_end(args); #ifdef WIN32 OutputDebugString(buf); #else cout << buf; #endif } /* ************************************************************************* */ Vector Vector_( size_t m, const double* const data) { Vector v(m); copy(data, data+m, v.data().begin()); return v; } /* ************************************************************************* */ Vector Vector_(size_t m, ...) { Vector v(m); va_list ap; va_start(ap, m); for( size_t i = 0 ; i < m ; i++) { double value = va_arg(ap, double); v(i) = value; } va_end(ap); return v; } /* ************************************************************************* */ bool zero(const Vector& v) { bool result = true; size_t n = v.size(); for( size_t j = 0 ; j < n ; j++) result = result && (v(j) == 0.0); return result; } /* ************************************************************************* */ Vector repeat(size_t n, double value) { Vector v(n, value); return v; } /* ************************************************************************* */ Vector delta(size_t n, size_t i, double value) { Vector v = zero(n); v(i) = value; return v; } /* ************************************************************************* */ void print(const Vector& v, const string& s) { size_t n = v.size(); odprintf("%s [", s.c_str()); for(size_t i=0; i= it2[i])) return false; return true; } /* ************************************************************************* */ bool equal_with_abs_tol(const Vector& vec1, const Vector& vec2, double tol) { Vector::const_iterator it1 = vec1.begin(); Vector::const_iterator it2 = vec2.begin(); if (vec1.size()!=vec2.size()) return false; for(size_t i=0; i tol) return false; } return true; } /* ************************************************************************* */ bool assert_equal(const Vector& expected, const Vector& actual, double tol) { if (equal_with_abs_tol(expected,actual,tol)) return true; cout << "not equal:" << endl; print(expected, "expected"); print(actual, "actual"); return false; } /* ************************************************************************* */ Vector sub(const Vector &v, size_t i1, size_t i2) { size_t n = i2-i1; Vector v_return(n); for( size_t i = 0; i < n; i++ ) v_return(i) = v(i1 + i); return v_return; } /* ************************************************************************* */ Vector emul(const Vector &a, const Vector &b) { size_t n = a.size(); assert (b.size()==n); Vector c(n); for( size_t i = 0; i < n; i++ ) c(i) = a(i)*b(i); return c; } /* ************************************************************************* */ Vector ediv(const Vector &a, const Vector &b) { size_t n = a.size(); assert (b.size()==n); Vector c(n); for( size_t i = 0; i < n; i++ ) c(i) = a(i)/b(i); return c; } /* ************************************************************************* */ Vector ediv_(const Vector &a, const Vector &b) { size_t n = a.size(); assert (b.size()==n); Vector c(n); for( size_t i = 0; i < n; i++ ) { double ai = a(i), bi = b(i); c(i) = (bi==0.0 && ai==0.0) ? 0.0 : a(i)/b(i); } return c; } /* ************************************************************************* */ double sum(const Vector &a) { double result = 0.0; size_t n = a.size(); for( size_t i = 0; i < n; i++ ) result += a(i); return result; } /* ************************************************************************* */ Vector reciprocal(const Vector &a) { size_t n = a.size(); Vector b(n); for( size_t i = 0; i < n; i++ ) b(i) = 1.0/a(i); return b; } /* ************************************************************************* */ Vector esqrt(const Vector& v) { Vector s(v.size()); transform(v.begin(), v.end(), s.begin(), ::sqrt); return s; } /* ************************************************************************* */ Vector abs(const Vector& v) { Vector s(v.size()); transform(v.begin(), v.end(), s.begin(), ::fabs); return s; } /* ************************************************************************* */ double max(const Vector &a) { return *(std::max_element(a.begin(), a.end())); } /* ************************************************************************* */ Vector operator/(double s, const Vector& v) { Vector result(v.size()); for(size_t i = 0; i < v.size(); i++) result[i] = s / v[i]; return result; } /* ************************************************************************* */ pair house(const Vector &x) { const double x0 = x(0); const double x02 = x0*x0; // old code - GSL verison was actually a bit slower const double sigma = inner_prod(trans(x),x) - x02; double beta = 0.0; Vector v(x); v(0) = 1.0; if( sigma == 0.0 ) beta = 0.0; else { double mu = sqrt(x02 + sigma); if( x0 <= 0.0 ) v(0) = x0 - mu; else v(0) = -sigma / (x0 + mu); const double v02 = v(0)*v(0); beta = 2.0 * v02 / (sigma + v02); v = v / v(0); } return make_pair(beta, v); } /* ************************************************************************* */ // Fast version *no error checking* ! // Pass in initialized vector of size m or will crash ! double weightedPseudoinverse(const Vector& a, const Vector& weights, Vector& pseudo) { size_t m = weights.size(); static const double inf = std::numeric_limits::infinity(); // Check once for zero entries of a. TODO: really needed ? vector isZero; for (size_t i = 0; i < m; ++i) isZero.push_back(fabs(a[i]) < 1e-9); // If there is a valid (a!=0) constraint (sigma==0) return the first one for (size_t i = 0; i < m; ++i) if (weights[i] == inf && !isZero[i]) { pseudo = delta(m, i, 1 / a[i]); return inf; } // Form psuedo-inverse inv(a'inv(Sigma)a)a'inv(Sigma) // For diagonal Sigma, inv(Sigma) = diag(precisions) double precision = 0; for (size_t i = 0; i < m; i++) { double ai = a[i]; if (!isZero[i]) // also catches remaining sigma==0 rows precision += weights[i] * (ai * ai); } // precision = a'inv(Sigma)a if (precision < 1e-9) for (size_t i = 0; i < m; i++) pseudo[i] = 0; else { // emul(precisions,a)/precision double variance = 1.0 / precision; for (size_t i = 0; i < m; i++) pseudo[i] = isZero[i] ? 0 : variance * weights[i] * a[i]; } return precision; // sum of weights } /* ************************************************************************* */ // Slow version with error checking pair weightedPseudoinverse(const Vector& a, const Vector& weights) { size_t m = weights.size(); if (a.size() != m) throw invalid_argument("a and weights have different sizes!"); Vector pseudo(m); double precision = weightedPseudoinverse(a, weights, pseudo); return make_pair(pseudo, precision); } /* ************************************************************************* */ Vector concatVectors(const std::list& vs) { size_t dim = 0; BOOST_FOREACH(Vector v, vs) dim += v.size(); Vector A(dim); size_t index = 0; BOOST_FOREACH(Vector v, vs) { for(size_t d = 0; d < v.size(); d++) A(d+index) = v(d); index += v.size(); } return A; } /* ************************************************************************* */ Vector concatVectors(size_t nrVectors, ...) { va_list ap; list vs; va_start(ap, nrVectors); for( size_t i = 0 ; i < nrVectors ; i++) { Vector* V = va_arg(ap, Vector*); vs.push_back(*V); } va_end(ap); return concatVectors(vs); } /* ************************************************************************* */ Vector rand_vector_norm(size_t dim, double mean, double sigma) { boost::normal_distribution norm_dist(mean, sigma); boost::variate_generator > norm(generator, norm_dist); Vector v(dim); Vector::iterator it_v; for(it_v=v.begin(); it_v!=v.end(); it_v++) *it_v = norm(); return v; } /* ************************************************************************* */ } // namespace gtsam