Vector.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
20 #include <gtsam/base/Vector.h>
21 #include <boost/optional.hpp>
22 #include <stdexcept>
23 #include <cstdarg>
24 #include <limits>
25 #include <iostream>
26 #include <fstream>
27 #include <sstream>
28 #include <iomanip>
29 #include <cmath>
30 #include <cstdio>
31 #include <vector>
32 
33 using namespace std;
34 
35 namespace gtsam {
36 
37 /* *************************************************************************
38  * References:
39  * 1. https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
40  * 2. https://floating-point-gui.de/errors/comparison/
41  * ************************************************************************* */
42 bool fpEqual(double a, double b, double tol, bool check_relative_also) {
43  using std::abs;
44  using std::isnan;
45  using std::isinf;
46 
47  double DOUBLE_MIN_NORMAL = numeric_limits<double>::min() + 1.0;
48  double larger = (abs(b) > abs(a)) ? abs(b) : abs(a);
49 
50  // handle NaNs
51  if(isnan(a) || isnan(b)) {
52  return isnan(a) && isnan(b);
53  }
54  // handle inf
55  else if(isinf(a) || isinf(b)) {
56  return isinf(a) && isinf(b);
57  }
58  // If the two values are zero or both are extremely close to it
59  // relative error is less meaningful here
60  else if(a == 0 || b == 0 || (abs(a) + abs(b)) < DOUBLE_MIN_NORMAL) {
61  return abs(a-b) <= tol * DOUBLE_MIN_NORMAL;
62  }
63  // Check if the numbers are really close.
64  // Needed when comparing numbers near zero or tol is in vicinity.
65  else if (abs(a - b) <= tol) {
66  return true;
67  }
68  // Check for relative error
69  else if (abs(a - b) <=
70  tol * min(larger, std::numeric_limits<double>::max()) &&
71  check_relative_also) {
72  return true;
73  }
74 
75  return false;
76 }
77 
78 /* ************************************************************************* */
79 //3 argument call
80 void print(const Vector& v, const string& s, ostream& stream) {
81  size_t n = v.size();
82 
83  stream << s << "[";
84  for(size_t i=0; i<n; i++) {
85  stream << setprecision(9) << v(i) << (i<n-1 ? "; " : "");
86  }
87  stream << "];" << endl;
88 }
89 
90 /* ************************************************************************* */
91 //1 or 2 argument call
92 void print(const Vector& v, const string& s) {
93  print(v, s, cout);
94 }
95 
96 /* ************************************************************************* */
97 void save(const Vector& v, const string &s, const string& filename) {
98  fstream stream(filename.c_str(), fstream::out | fstream::app);
99  print(v, s + "=", stream);
100  stream.close();
101 }
102 
103 /* ************************************************************************* */
104 bool operator==(const Vector& vec1,const Vector& vec2) {
105  if (vec1.size() != vec2.size()) return false;
106  size_t m = vec1.size();
107  for(size_t i=0; i<m; i++)
108  if(vec1[i] != vec2[i])
109  return false;
110  return true;
111 }
112 
113 /* ************************************************************************* */
114 bool greaterThanOrEqual(const Vector& vec1, const Vector& vec2) {
115  size_t m = vec1.size();
116  for(size_t i=0; i<m; i++)
117  if(!(vec1[i] >= vec2[i]))
118  return false;
119  return true;
120 }
121 
122 /* ************************************************************************* */
123 bool equal_with_abs_tol(const Vector& vec1, const Vector& vec2, double tol) {
124  if (vec1.size()!=vec2.size()) return false;
125  size_t m = vec1.size();
126  for(size_t i=0; i<m; ++i) {
127  if (!fpEqual(vec1[i], vec2[i], tol))
128  return false;
129  }
130  return true;
131 }
132 
133 /* ************************************************************************* */
134 bool equal_with_abs_tol(const SubVector& vec1, const SubVector& vec2, double tol) {
135  if (vec1.size()!=vec2.size()) return false;
136  size_t m = vec1.size();
137  for(size_t i=0; i<m; ++i) {
138  if (!fpEqual(vec1[i], vec2[i], tol))
139  return false;
140  }
141  return true;
142 }
143 
144 /* ************************************************************************* */
145 bool assert_equal(const Vector& expected, const Vector& actual, double tol) {
146  if (equal_with_abs_tol(expected,actual,tol)) return true;
147  cout << "not equal:" << endl;
148  print(expected, "expected");
149  print(actual, "actual");
150  return false;
151 }
152 
153 /* ************************************************************************* */
154 bool assert_inequal(const Vector& expected, const Vector& actual, double tol) {
155  if (!equal_with_abs_tol(expected,actual,tol)) return true;
156  cout << "Erroneously equal:" << endl;
157  print(expected, "expected");
158  print(actual, "actual");
159  return false;
160 }
161 
162 /* ************************************************************************* */
163 bool assert_equal(const SubVector& expected, const SubVector& actual, double tol) {
164  if (equal_with_abs_tol(expected,actual,tol)) return true;
165  cout << "not equal:" << endl;
166  print(static_cast<Vector>(expected), "expected");
167  print(static_cast<Vector>(actual), "actual");
168  return false;
169 }
170 
171 /* ************************************************************************* */
172 bool assert_equal(const ConstSubVector& expected, const ConstSubVector& actual, double tol) {
173  if (equal_with_abs_tol(Vector(expected),Vector(actual),tol)) return true;
174  cout << "not equal:" << endl;
175  print(Vector(expected), "expected");
176  print(Vector(actual), "actual");
177  return false;
178 }
179 
180 /* ************************************************************************* */
181 bool linear_dependent(const Vector& vec1, const Vector& vec2, double tol) {
182  if (vec1.size()!=vec2.size()) return false;
183  bool flag = false; double scale = 1.0;
184  size_t m = vec1.size();
185  for(size_t i=0; i<m; i++) {
186  if((std::abs(vec1[i])>tol && std::abs(vec2[i])<tol) || (std::abs(vec1[i])<tol && std::abs(vec2[i])>tol))
187  return false;
188  if(vec1[i] == 0 && vec2[i] == 0) continue;
189  if (!flag) {
190  scale = vec1[i] / vec2[i];
191  flag = true ;
192  }
193  else if (std::abs(vec1[i] - vec2[i]*scale) > tol) return false;
194  }
195  return flag;
196 }
197 
198 /* ************************************************************************* */
199 Vector ediv_(const Vector &a, const Vector &b) {
200  size_t n = a.size();
201  assert (b.size()==a.size());
202  Vector c(n);
203  for( size_t i = 0; i < n; i++ ) {
204  const double &ai = a(i), &bi = b(i);
205  c(i) = (bi==0.0 && ai==0.0) ? 0.0 : ai/bi;
206  }
207  return c;
208 }
209 
210 /* ************************************************************************* */
211 // imperative version, pass in x
213  const double x0 = v(0);
214  const double x02 = x0*x0;
215 
216  // old code - GSL verison was actually a bit slower
217  const double sigma = v.squaredNorm() - x02;
218 
219  v(0) = 1.0;
220 
221  if( sigma == 0.0 )
222  return 0.0;
223  else {
224  double mu = sqrt(x02 + sigma);
225  if( x0 <= 0.0 )
226  v(0) = x0 - mu;
227  else
228  v(0) = -sigma / (x0 + mu);
229 
230  const double v02 = v(0)*v(0);
231  v = v / v(0);
232  return 2.0 * v02 / (sigma + v02);
233  }
234 }
235 
236 /* ************************************************************************* */
237 pair<double, Vector > house(const Vector &x) {
238  Vector v(x);
239  double beta = houseInPlace(v);
240  return make_pair(beta, v);
241 }
242 
243 /* ************************************************************************* */
244 // Fast version *no error checking* !
245 // Pass in initialized vector of size m or will crash !
246 double weightedPseudoinverse(const Vector& a, const Vector& weights,
247  Vector& pseudo) {
248 
249  size_t m = weights.size();
250  static const double inf = std::numeric_limits<double>::infinity();
251 
252  // Check once for zero entries of a. TODO: really needed ?
253  vector<bool> isZero;
254  for (size_t i = 0; i < m; ++i) isZero.push_back(std::abs(a[i]) < 1e-9);
255 
256  // If there is a valid (a!=0) constraint (sigma==0) return the first one
257  for (size_t i = 0; i < m; ++i) {
258  if (weights[i] == inf && !isZero[i]) {
259  // Basically, instead of doing a normal QR step with the weighted
260  // pseudoinverse, we enforce the constraint by turning
261  // ax + AS = b into x + (A/a)S = b/a, for the first row where a!=0
262  pseudo = Vector::Unit(m,i)*(1.0/a[i]);
263  return inf;
264  }
265  }
266 
267  // Form psuedo-inverse inv(a'inv(Sigma)a)a'inv(Sigma)
268  // For diagonal Sigma, inv(Sigma) = diag(precisions)
269  double precision = 0;
270  for (size_t i = 0; i < m; i++) {
271  double ai = a[i];
272  if (!isZero[i]) // also catches remaining sigma==0 rows
273  precision += weights[i] * (ai * ai);
274  }
275 
276  // precision = a'inv(Sigma)a
277  if (precision < 1e-9)
278  for (size_t i = 0; i < m; i++)
279  pseudo[i] = 0;
280  else {
281  // emul(precisions,a)/precision
282  double variance = 1.0 / precision;
283  for (size_t i = 0; i < m; i++)
284  pseudo[i] = isZero[i] ? 0 : variance * weights[i] * a[i];
285  }
286  return precision; // sum of weights
287 }
288 
289 /* ************************************************************************* */
290 // Slow version with error checking
291 pair<Vector, double>
292 weightedPseudoinverse(const Vector& a, const Vector& weights) {
293  DenseIndex m = weights.size();
294  if (a.size() != m)
295  throw invalid_argument("a and weights have different sizes!");
296  Vector pseudo(m);
297  double precision = weightedPseudoinverse(a, weights, pseudo);
298  return make_pair(pseudo, precision);
299 }
300 
301 /* ************************************************************************* */
302 Vector concatVectors(const std::list<Vector>& vs)
303 {
304  size_t dim = 0;
305  for(Vector v: vs)
306  dim += v.size();
307 
308  Vector A(dim);
309  size_t index = 0;
310  for(Vector v: vs) {
311  for(int d = 0; d < v.size(); d++)
312  A(d+index) = v(d);
313  index += v.size();
314  }
315 
316  return A;
317 }
318 
319 /* ************************************************************************* */
320 Vector concatVectors(size_t nrVectors, ...)
321 {
322  va_list ap;
323  list<Vector> vs;
324  va_start(ap, nrVectors);
325  for( size_t i = 0 ; i < nrVectors ; i++) {
326  Vector* V = va_arg(ap, Vector*);
327  vs.push_back(*V);
328  }
329  va_end(ap);
330  return concatVectors(vs);
331 }
332 
333 } // namespace gtsam
Matrix3f m
bool linear_dependent(const Vector &vec1, const Vector &vec2, double tol)
Definition: Vector.cpp:181
#define max(a, b)
Definition: datatypes.h:20
Vector ediv_(const Vector &a, const Vector &b)
Definition: Vector.cpp:199
const mpreal ai(const mpreal &x, mp_rnd_t r=mpreal::get_default_rnd())
Definition: mpreal.h:2467
Vector concatVectors(size_t nrVectors,...)
Definition: Vector.cpp:320
pair< Vector, double > weightedPseudoinverse(const Vector &a, const Vector &weights)
Definition: Vector.cpp:292
Scalar * b
Definition: benchVecAdd.cpp:17
#define min(a, b)
Definition: datatypes.h:19
Matrix expected
Definition: testMatrix.cpp:974
double mu
ArrayXcf v
Definition: Cwise_arg.cpp:1
static const double sigma
int n
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
bool assert_equal(const ConstSubVector &expected, const ConstSubVector &actual, double tol)
Definition: Vector.cpp:172
Definition: Half.h:150
#define isinf(X)
Definition: main.h:73
bool equal_with_abs_tol(const SubVector &vec1, const SubVector &vec2, double tol)
Definition: Vector.cpp:134
bool assert_inequal(const Vector &expected, const Vector &actual, double tol)
Definition: Vector.cpp:154
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:67
Array33i a
bool fpEqual(double a, double b, double tol, bool check_relative_also)
Definition: Vector.cpp:42
void print(const Vector &v, const string &s)
Definition: Vector.cpp:92
void save(const Vector &v, const string &s, const string &filename)
Definition: Vector.cpp:97
Expression of a fixed-size or dynamic-size sub-vector.
Eigen::VectorXd Vector
Definition: Vector.h:38
Array< double, 1, 3 > e(1./3., 0.5, 2.)
RealScalar s
bool greaterThanOrEqual(const Vector &vec1, const Vector &vec2)
Definition: Vector.cpp:114
static Symbol x0('x', 0)
const mpreal dim(const mpreal &a, const mpreal &b, mp_rnd_t r=mpreal::get_default_rnd())
Definition: mpreal.h:2201
traits
Definition: chartTesting.h:28
typedef and functions to augment Eigen&#39;s VectorXd
RowVectorXd vec1(3)
static double inf
Definition: testMatrix.cpp:30
bool operator==(const NonZeroIterator< std::pair< A, B >> &it, const NonZeroSentinel &)
cout precision(2)
pair< double, Vector > house(const Vector &x)
Definition: Vector.cpp:237
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy y set format x g set format y g set format x2 g set format y2 g set format z g set angles radians set nogrid set key title set key left top Right noreverse box linetype linewidth samplen spacing width set nolabel set noarrow set nologscale set logscale x set set pointsize set encoding default set nopolar set noparametric set set set set surface set nocontour set clabel set mapping cartesian set nohidden3d set cntrparam order set cntrparam linear set cntrparam levels auto set cntrparam points set size set set xzeroaxis lt lw set x2zeroaxis lt lw set yzeroaxis lt lw set y2zeroaxis lt lw set tics in set ticslevel set tics scale
const G double tol
Definition: Group.h:83
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
#define abs(x)
Definition: datatypes.h:17
Eigen::Matrix< double, Eigen::Dynamic, 1 > Vector
double houseInPlace(Vector &v)
Definition: Vector.cpp:212
#define isnan(X)
Definition: main.h:72


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:51:23