Developer Documentation
unittests_vector_type.cc
1 #include <gtest/gtest.h>
2 #include <Unittests/unittests_common.hh>
3 #include <iostream>
4 #include <list>
5 
6 #include <stdint.h>
7 
8 namespace {
9 
10 class OpenMeshVectorTest : public testing::Test {
11 
12  protected:
13 
14  // This function is called before each test is run
15  virtual void SetUp() {
16 
17  // Do some initial stuff with the member data here...
18  }
19 
20  // This function is called after all tests are through
21  virtual void TearDown() {
22 
23  // Do some final stuff with the member data here...
24  }
25 
26 };
27 
28 
29 
30 /*
31  * ====================================================================
32  * Define tests below
33  * ====================================================================
34  */
35 
36 /* Compute surface area via cross product
37  */
38 TEST_F(OpenMeshVectorTest, ComputeTriangleSurfaceWithCrossProduct) {
39 
40 
41  //
42  // vec1
43  // x
44  // |
45  // |
46  // |
47  // x------>x vec2
48  //
49 
50  OpenMesh::Vec3d vec1(0.0,1.0,0.0);
51  OpenMesh::Vec3d vec2(1.0,0.0,0.0);
52 
53  double area = 0.5 * cross(vec1,vec2).norm();
54  EXPECT_EQ(0.5f , area ) << "Wrong area in cross product function";
55 
56  area = 0.5 * ( vec1 % vec2 ).norm();
57  EXPECT_EQ(0.5f , area ) << "Wrong area in cross product operator";
58 
59 }
60 
61 /* Check OpenMesh Vector type abs function
62  */
63 TEST_F(OpenMeshVectorTest, AbsTest) {
64 
65  OpenMesh::Vec3d vec1(0.5,0.5,-0.5);
66 
67  EXPECT_EQ( vec1.l8_norm() , 0.5f ) << "Wrong l8norm computation";
68 
69 }
70 
71 /* Compute surface area via cross product
72  */
73 TEST_F(OpenMeshVectorTest, VectorCasting) {
74 
75  OpenMesh::Vec3d vecd(1.0,2.0,3.0);
77  EXPECT_EQ(1.f, vecf[0]) << "vector type cast failed on component 0";
78  EXPECT_EQ(2.f, vecf[1]) << "vector type cast failed on component 1";
79  EXPECT_EQ(3.f, vecf[2]) << "vector type cast failed on component 2";
80 
81  OpenMesh::Vec4d vecd4(40.0,30.0,20.0,10.0);
83  EXPECT_EQ(40.0, vecd[0]) << "vector dimension cast failed on component 0";
84  EXPECT_EQ(30.0, vecd[1]) << "vector dimension cast failed on component 1";
85  EXPECT_EQ(20.0, vecd[2]) << "vector dimension cast failed on component 2";
86 
87 }
88 
89 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
90 TEST_F(OpenMeshVectorTest, cpp11_constructors) {
91  OpenMesh::Vec3d vec1 { 1.2, 2.0, 3.0 };
92 
93  EXPECT_EQ(1.2, vec1[0]);
94  EXPECT_EQ(2.0, vec1[1]);
95  EXPECT_EQ(3.0, vec1[2]);
96 
97  OpenMesh::Vec4f vec2 { 1.2f, 3.5f, 1.0f, 0.0f };
98 
99  EXPECT_EQ(1.2f, vec2[0]);
100  EXPECT_EQ(3.5f, vec2[1]);
101  EXPECT_EQ(1.0f, vec2[2]);
102  EXPECT_EQ(0.0f, vec2[3]);
103 
104  OpenMesh::Vec4f vec2b { vec2 };
105 
106  EXPECT_EQ(1.2f, vec2b[0]);
107  EXPECT_EQ(3.5f, vec2b[1]);
108  EXPECT_EQ(1.0f, vec2b[2]);
109  EXPECT_EQ(0.0f, vec2b[3]);
110 
111  OpenMesh::Vec4d vec4d { 1.23 };
112  EXPECT_EQ(1.23, vec4d[0]);
113  EXPECT_EQ(1.23, vec4d[1]);
114  EXPECT_EQ(1.23, vec4d[2]);
115  EXPECT_EQ(1.23, vec4d[3]);
116 }
117 
118 TEST_F(OpenMeshVectorTest, cpp11_htmlColorLiteral) {
119  static constexpr OpenMesh::Vec4f rose = 0xFFC7F1FF_htmlColor;
120 
121  EXPECT_EQ(0xFFC7F1FF_htmlColor, rose);
122 
123  const OpenMesh::Vec4f light_blue = 0x1FCFFFFF_htmlColor;
124  EXPECT_LE((OpenMesh::Vec4f(0.1215686274f, 0.8117647058f, 1.0f, 1.0f)
125  - light_blue).sqrnorm(), 1e-10);
126 
127  const auto light_blue_2 = 0x1FCFFFFF_htmlColor;
128  // Check whether auto type deduction works as expected.
129  static_assert(std::is_same<decltype(light_blue_2), decltype(light_blue)>
130  ::value, "Bad type deduced from _htmlColor literal.");
131  EXPECT_EQ(light_blue, light_blue_2);
132 }
133 
134 
135 namespace {
136 class C {
137  public:
138  C() {}
139  C(const C &rhs) { ADD_FAILURE() << "Copy constructor used."; }
140  C(C &&rhs) { ++copy_con; }
141  C &operator= (const C &rhs) {
142  ADD_FAILURE() << "Copy assignemnt used.";
143  return *this;
144  }
145  C &operator= (C &&rhs) { ++copy_ass; return *this; }
146 
147  static int copy_con;
148  static int copy_ass;
149 };
150 
151 int C::copy_con = 0;
152 int C::copy_ass = 0;
153 }
154 
160 TEST_F(OpenMeshVectorTest, move_constructor_assignment) {
161 
162  C::copy_con = 0;
163  C::copy_ass = 0;
164 
165  // Test move assigning.
167  x = std::move(y);
168  EXPECT_EQ(3, C::copy_ass);
169  EXPECT_EQ(0, C::copy_con);
170 
171  // Test move constructing.
172  OpenMesh::VectorT<C, 3> z(std::move(x));
173  EXPECT_EQ(3, C::copy_ass);
174  EXPECT_EQ(3, C::copy_con);
175 }
176 
177 TEST_F(OpenMeshVectorTest, iterator_init) {
178  std::list<float> a;
179  a.push_back(1.0);
180  a.push_back(2.0);
181  a.push_back(3.0);
182  OpenMesh::Vec3f v(a.begin());
183  EXPECT_EQ(OpenMesh::Vec3f(1.0, 2.0, 3.0), v);
184 }
185 
186 #endif // C++11
187 
188 
189 TEST_F(OpenMeshVectorTest, BasicArithmeticInPlace) {
190  OpenMesh::Vec3d v1(1, 2, 3);
191  double s1 = 2;
192  const double epsilon = 1e-6;
193 
194  OpenMesh::Vec3d v2add (3, 4, 6); v2add += v1;
195  OpenMesh::Vec3d v2sub (3, 4, 6); v2sub -= v1;
196  OpenMesh::Vec3d v2cmul(3, 4, 6); v2cmul *= v1;
197  OpenMesh::Vec3d v2cdiv(3, 4, 6); v2cdiv /= v1;
198  OpenMesh::Vec3d v2smul(3, 4, 6); v2smul *= s1;
199  OpenMesh::Vec3d v2sdiv(3, 4, 6); v2sdiv /= s1;
200 
201  EXPECT_NEAR(4, v2add[0], epsilon);
202  EXPECT_NEAR(6, v2add[1], epsilon);
203  EXPECT_NEAR(9, v2add[2], epsilon);
204 
205  EXPECT_NEAR(2, v2sub[0], epsilon);
206  EXPECT_NEAR(2, v2sub[1], epsilon);
207  EXPECT_NEAR(3, v2sub[2], epsilon);
208 
209  EXPECT_NEAR( 3, v2cmul[0], epsilon);
210  EXPECT_NEAR( 8, v2cmul[1], epsilon);
211  EXPECT_NEAR(18, v2cmul[2], epsilon);
212 
213  EXPECT_NEAR(3, v2cdiv[0], epsilon);
214  EXPECT_NEAR(2, v2cdiv[1], epsilon);
215  EXPECT_NEAR(2, v2cdiv[2], epsilon);
216 
217  EXPECT_NEAR( 6, v2smul[0], epsilon);
218  EXPECT_NEAR( 8, v2smul[1], epsilon);
219  EXPECT_NEAR(12, v2smul[2], epsilon);
220 
221  EXPECT_NEAR(1.5, v2sdiv[0], epsilon);
222  EXPECT_NEAR(2.0, v2sdiv[1], epsilon);
223  EXPECT_NEAR(3.0, v2sdiv[2], epsilon);
224 }
225 
226 TEST_F(OpenMeshVectorTest, BasicArithmeticImmutable) {
227  OpenMesh::Vec3d v1(1, 2, 3);
228  const double epsilon = 1e-6;
229 
230  OpenMesh::Vec3d v2add = v1 + OpenMesh::Vec3d(2, 4, 6);
231  OpenMesh::Vec3d v2sub = v1 - OpenMesh::Vec3d(2, 4, 6);
232  OpenMesh::Vec3d v2cmul = v1 * OpenMesh::Vec3d(2, 4, 6);
233  OpenMesh::Vec3d v2cdiv = v1 / OpenMesh::Vec3d(2, 4, 6);
234  OpenMesh::Vec3d v2smul = v1 * 2.0;
235  OpenMesh::Vec3d v2sdiv = v1 / 2.0;
236  OpenMesh::Vec3d v2neg = -v1;
237 
238  EXPECT_NEAR(3, v2add[0], epsilon);
239  EXPECT_NEAR(6, v2add[1], epsilon);
240  EXPECT_NEAR(9, v2add[2], epsilon);
241 
242  EXPECT_NEAR(-1, v2sub[0], epsilon);
243  EXPECT_NEAR(-2, v2sub[1], epsilon);
244  EXPECT_NEAR(-3, v2sub[2], epsilon);
245 
246  EXPECT_NEAR( 2, v2cmul[0], epsilon);
247  EXPECT_NEAR( 8, v2cmul[1], epsilon);
248  EXPECT_NEAR(18, v2cmul[2], epsilon);
249 
250  EXPECT_NEAR(0.5, v2cdiv[0], epsilon);
251  EXPECT_NEAR(0.5, v2cdiv[1], epsilon);
252  EXPECT_NEAR(0.5, v2cdiv[2], epsilon);
253 
254  EXPECT_NEAR(2, v2smul[0], epsilon);
255  EXPECT_NEAR(4, v2smul[1], epsilon);
256  EXPECT_NEAR(6, v2smul[2], epsilon);
257 
258  EXPECT_NEAR(0.5, v2sdiv[0], epsilon);
259  EXPECT_NEAR(1.0, v2sdiv[1], epsilon);
260  EXPECT_NEAR(1.5, v2sdiv[2], epsilon);
261 
262  EXPECT_NEAR(-1, v2neg[0], epsilon);
263  EXPECT_NEAR(-2, v2neg[1], epsilon);
264  EXPECT_NEAR(-3, v2neg[2], epsilon);
265 }
266 
267 TEST_F(OpenMeshVectorTest, BasicLinearAlgebra) {
268  OpenMesh::Vec3d v(1, 2, 3);
269  EXPECT_EQ(v[0], 1.0);
270  EXPECT_EQ(v[1], 2.0);
271  EXPECT_EQ(v[2], 3.0);
272 
273  EXPECT_EQ(OpenMesh::Vec3d(-1, -2, -3), -v);
274  EXPECT_EQ(3, OpenMesh::Vec3d(1, 3, 2).max());
275  EXPECT_EQ(3, OpenMesh::Vec3d(1, 2, 3).max());
276  EXPECT_EQ(3, OpenMesh::Vec3d(1, 3, -4).max());
277  EXPECT_EQ(3, OpenMesh::Vec3d(-4, 2, 3).max());
278  EXPECT_EQ(4, OpenMesh::Vec3d(1, 3, -4).max_abs());
279  EXPECT_EQ(4, OpenMesh::Vec3d(-4, 2, 3).max_abs());
280 
281  EXPECT_EQ(1, OpenMesh::Vec3d(1, 3, 2).min());
282  EXPECT_EQ(1, OpenMesh::Vec3d(1, 2, 3).min());
283  EXPECT_EQ(-4, OpenMesh::Vec3d(1, 3, -4).min());
284  EXPECT_EQ(-4, OpenMesh::Vec3d(-4, 2, 3).min());
285  EXPECT_EQ(1, OpenMesh::Vec3d(1, 3, -4).min_abs());
286  EXPECT_EQ(2, OpenMesh::Vec3d(-4, 2, 3).min_abs());
287 
288  EXPECT_NEAR(14, OpenMesh::Vec3d(1, 2, 3) | OpenMesh::Vec3d(1, 2, 3), 1e-6);
289  EXPECT_NEAR(-14, OpenMesh::Vec3d(1, 2, 3) | OpenMesh::Vec3d(-1, -2, -3), 1e-6);
290  EXPECT_NEAR(14, OpenMesh::Vec3d(-1, -2, -3) | OpenMesh::Vec3d(-1, -2, -3), 1e-6);
291 }
292 
293 TEST_F(OpenMeshVectorTest, array_init) {
294  float a[3]; a[0] = 1.0; a[1] = 2.0; a[2] = 3.0;
295  OpenMesh::Vec3f v(a);
296  EXPECT_EQ(OpenMesh::Vec3f(1.0, 2.0, 3.0), v);
297 
298  // This should not invoke the array constructor.
299  OpenMesh::Vec3d v2(3.0f);
300 }
301 
302 TEST_F(OpenMeshVectorTest, normalized_cond) {
303  OpenMesh::Vec3d v1(1, -2, 3), v2(0, 0, 0);
304  EXPECT_EQ(OpenMesh::Vec3d(0, 0, 0), v2.normalize_cond());
305  const OpenMesh::Vec3d r1 =
307  0.2672612419124244,
308  -0.5345224838248488,
309  0.8017837257372732) - v1.normalize_cond();
310  EXPECT_NEAR(r1[0], 0.0, 1e-12);
311  EXPECT_NEAR(r1[1], 0.0, 1e-12);
312  EXPECT_NEAR(r1[2], 0.0, 1e-12);
313 }
314 
315 TEST_F(OpenMeshVectorTest, size_dim) {
316  OpenMesh::Vec3d v3d(1, 2, 3);
317  OpenMesh::Vec3f v3f(1, 2, 3);
318  OpenMesh::Vec2i v2i(1, 2);
319 
320  EXPECT_EQ(3u, v3d.size());
321  EXPECT_EQ(3, v3d.dim());
322  EXPECT_EQ(3u, v3f.size());
323  EXPECT_EQ(3, v3f.dim());
324  EXPECT_EQ(2u, v2i.size());
325  EXPECT_EQ(2, v2i.dim());
326 }
327 
328 class OpenMeshVectorGCCBugTest;
329 void trigger_alignment_bug(OpenMeshVectorGCCBugTest &obj);
330 
336 class OpenMeshVectorGCCBugTest : public testing::Test {
337 
338  protected:
339 
340  virtual void SetUp() {
341  /*
342  * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as
343  * pointless as it may look, is carefully crafted to provoke
344  * the GCC optimizer bug mentioned above.
345  */
346  testfn = trigger_alignment_bug;
347  vec1 = OpenMesh::Vec4f(1.0f, 2.0f, 3.0f, 4.0f);
348  vec2 = OpenMesh::Vec4f(5.0f, 6.0f, 7.0f, 8.0f);
349  padding = 42;
350  }
351 
352  virtual void TearDown() {
353  // Do some final stuff with the member data here...
354  }
355 
356  public:
357  /*
358  * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as
359  * pointless as it may look, is carefully crafted to provoke
360  * the GCC optimizer bug mentioned above.
361  */
362  int32_t padding;
363  OpenMesh::Vec4f vec1, vec2;
364  void (*testfn)(OpenMeshVectorGCCBugTest &obj);
365 
366  OpenMesh::Vec4f &get_vec1() { return vec1; }
367  OpenMesh::Vec4f &get_vec2() { return vec2; }
368 };
369 
370 void trigger_alignment_bug(OpenMeshVectorGCCBugTest &obj) {
371  /*
372  * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as
373  * pointless as it may look, is carefully crafted to provoke
374  * the GCC optimizer bug mentioned above.
375  */
376  int x1 = 1;
377 
378  OpenMesh::Vec4f vec3 = obj.get_vec1();
379  OpenMesh::Vec4f vec4 = obj.get_vec2();
380  vec3 += vec4;
381 
382  EXPECT_EQ(1, x1);
383  EXPECT_EQ(42, obj.padding);
384  EXPECT_EQ(6.0f, vec3[0]);
385  EXPECT_EQ(8.0f, vec3[1]);
386  EXPECT_EQ(10.0f, vec3[2]);
387  EXPECT_EQ(12.0f, vec3[3]);
388 }
389 
390 TEST_F(OpenMeshVectorGCCBugTest, alignment_bug) {
391  /*
392  * WARNING: DO NOT CHANGE ANYTHGIN! Every single line, as
393  * pointless as it may look, is carefully crafted to provoke
394  * the GCC optimizer bug mentioned above.
395  */
396  (*testfn)(*this);
397 }
398 
399 
400 }
void vector_cast(const src_t &_src, dst_t &_dst, GenProg::Int2Type< n >)
Cast vector type to another vector type by copying the vector elements.
Definition: vector_cast.hh:86
VectorT< float, 4 > Vec4f
Definition: Vector11T.hh:788
VectorT< double, 3 > Vec3d
Definition: Vector11T.hh:771
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
vector_type &::type normalize_cond()
compute squared euclidean norm
Definition: Vector11T.hh:455