• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #include "main.h"
11 #include <Eigen/Geometry>
12 #include <Eigen/LU>
13 #include <Eigen/SVD>
14 
non_projective_only()15 template<typename Scalar, int Mode, int Options> void non_projective_only()
16 {
17     /* this test covers the following files:
18      Cross.h Quaternion.h, Transform.cpp
19   */
20   typedef Matrix<Scalar,2,2> Matrix2;
21   typedef Matrix<Scalar,3,3> Matrix3;
22   typedef Matrix<Scalar,4,4> Matrix4;
23   typedef Matrix<Scalar,2,1> Vector2;
24   typedef Matrix<Scalar,3,1> Vector3;
25   typedef Matrix<Scalar,4,1> Vector4;
26   typedef Quaternion<Scalar> Quaternionx;
27   typedef AngleAxis<Scalar> AngleAxisx;
28   typedef Transform<Scalar,2,Mode,Options> Transform2;
29   typedef Transform<Scalar,3,Mode,Options> Transform3;
30   typedef Transform<Scalar,2,Isometry,Options> Isometry2;
31   typedef Transform<Scalar,3,Isometry,Options> Isometry3;
32   typedef typename Transform3::MatrixType MatrixType;
33   typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
34   typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
35   typedef Translation<Scalar,2> Translation2;
36   typedef Translation<Scalar,3> Translation3;
37 
38   Vector3 v0 = Vector3::Random(),
39           v1 = Vector3::Random();
40 
41   Transform3 t0, t1, t2;
42 
43   Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
44 
45   Quaternionx q1, q2;
46 
47   q1 = AngleAxisx(a, v0.normalized());
48 
49   t0 = Transform3::Identity();
50   VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
51 
52   t0.linear() = q1.toRotationMatrix();
53 
54   v0 << 50, 2, 1;
55   t0.scale(v0);
56 
57   VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).template head<3>().norm(), v0.x());
58 
59   t0.setIdentity();
60   t1.setIdentity();
61   v1 << 1, 2, 3;
62   t0.linear() = q1.toRotationMatrix();
63   t0.pretranslate(v0);
64   t0.scale(v1);
65   t1.linear() = q1.conjugate().toRotationMatrix();
66   t1.prescale(v1.cwiseInverse());
67   t1.translate(-v0);
68 
69   VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
70 
71   t1.fromPositionOrientationScale(v0, q1, v1);
72   VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
73   VERIFY_IS_APPROX(t1*v1, t0*v1);
74 
75   // translation * vector
76   t0.setIdentity();
77   t0.translate(v0);
78   VERIFY_IS_APPROX((t0 * v1).template head<3>(), Translation3(v0) * v1);
79 
80   // AlignedScaling * vector
81   t0.setIdentity();
82   t0.scale(v0);
83   VERIFY_IS_APPROX((t0 * v1).template head<3>(), AlignedScaling3(v0) * v1);
84 }
85 
transformations()86 template<typename Scalar, int Mode, int Options> void transformations()
87 {
88   /* this test covers the following files:
89      Cross.h Quaternion.h, Transform.cpp
90   */
91   typedef Matrix<Scalar,2,2> Matrix2;
92   typedef Matrix<Scalar,3,3> Matrix3;
93   typedef Matrix<Scalar,4,4> Matrix4;
94   typedef Matrix<Scalar,2,1> Vector2;
95   typedef Matrix<Scalar,3,1> Vector3;
96   typedef Matrix<Scalar,4,1> Vector4;
97   typedef Quaternion<Scalar> Quaternionx;
98   typedef AngleAxis<Scalar> AngleAxisx;
99   typedef Transform<Scalar,2,Mode,Options> Transform2;
100   typedef Transform<Scalar,3,Mode,Options> Transform3;
101   typedef Transform<Scalar,2,Isometry,Options> Isometry2;
102   typedef Transform<Scalar,3,Isometry,Options> Isometry3;
103   typedef typename Transform3::MatrixType MatrixType;
104   typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
105   typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
106   typedef Translation<Scalar,2> Translation2;
107   typedef Translation<Scalar,3> Translation3;
108 
109   Vector3 v0 = Vector3::Random(),
110           v1 = Vector3::Random();
111   Matrix3 matrot1, m;
112 
113   Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
114   Scalar s0 = internal::random<Scalar>();
115 
116   VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
117   VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
118   VERIFY_IS_APPROX(internal::cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
119   m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
120   VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
121   VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
122 
123   Quaternionx q1, q2;
124   q1 = AngleAxisx(a, v0.normalized());
125   q2 = AngleAxisx(a, v1.normalized());
126 
127   // rotation matrix conversion
128   matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
129           * AngleAxisx(Scalar(0.2), Vector3::UnitY())
130           * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
131   VERIFY_IS_APPROX(matrot1 * v1,
132        AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
133     * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
134     * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
135 
136   // angle-axis conversion
137   AngleAxisx aa = AngleAxisx(q1);
138   VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
139   VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
140 
141   aa.fromRotationMatrix(aa.toRotationMatrix());
142   VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
143   VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
144 
145   // AngleAxis
146   VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
147     Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
148 
149   AngleAxisx aa1;
150   m = q1.toRotationMatrix();
151   aa1 = m;
152   VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
153     Quaternionx(m).toRotationMatrix());
154 
155   // Transform
156   // TODO complete the tests !
157   a = 0;
158   while (internal::abs(a)<Scalar(0.1))
159     a = internal::random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
160   q1 = AngleAxisx(a, v0.normalized());
161   Transform3 t0, t1, t2;
162 
163   // first test setIdentity() and Identity()
164   t0.setIdentity();
165   VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
166   t0.matrix().setZero();
167   t0 = Transform3::Identity();
168   VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
169 
170   t0.setIdentity();
171   t1.setIdentity();
172   v1 << 1, 2, 3;
173   t0.linear() = q1.toRotationMatrix();
174   t0.pretranslate(v0);
175   t0.scale(v1);
176   t1.linear() = q1.conjugate().toRotationMatrix();
177   t1.prescale(v1.cwiseInverse());
178   t1.translate(-v0);
179 
180   VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
181 
182   t1.fromPositionOrientationScale(v0, q1, v1);
183   VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
184 
185   t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
186   t1.setIdentity(); t1.scale(v0).rotate(q1);
187   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
188 
189   t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
190   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
191 
192   VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
193   VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
194 
195   // More transform constructors, operator=, operator*=
196 
197   Matrix3 mat3 = Matrix3::Random();
198   Matrix4 mat4;
199   mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
200   Transform3 tmat3(mat3), tmat4(mat4);
201   if(Mode!=int(AffineCompact))
202     tmat4.matrix()(3,3) = Scalar(1);
203   VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
204 
205   Scalar a3 = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
206   Vector3 v3 = Vector3::Random().normalized();
207   AngleAxisx aa3(a3, v3);
208   Transform3 t3(aa3);
209   Transform3 t4;
210   t4 = aa3;
211   VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
212   t4.rotate(AngleAxisx(-a3,v3));
213   VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
214   t4 *= aa3;
215   VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
216 
217   v3 = Vector3::Random();
218   Translation3 tv3(v3);
219   Transform3 t5(tv3);
220   t4 = tv3;
221   VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
222   t4.translate(-v3);
223   VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
224   t4 *= tv3;
225   VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
226 
227   AlignedScaling3 sv3(v3);
228   Transform3 t6(sv3);
229   t4 = sv3;
230   VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
231   t4.scale(v3.cwiseInverse());
232   VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
233   t4 *= sv3;
234   VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
235 
236   // matrix * transform
237   VERIFY_IS_APPROX((t3.matrix()*t4).matrix(), (t3*t4).matrix());
238 
239   // chained Transform product
240   VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
241 
242   // check that Transform product doesn't have aliasing problems
243   t5 = t4;
244   t5 = t5*t5;
245   VERIFY_IS_APPROX(t5, t4*t4);
246 
247   // 2D transformation
248   Transform2 t20, t21;
249   Vector2 v20 = Vector2::Random();
250   Vector2 v21 = Vector2::Random();
251   for (int k=0; k<2; ++k)
252     if (internal::abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
253   t21.setIdentity();
254   t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
255   VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
256     t21.pretranslate(v20).scale(v21).matrix());
257 
258   t21.setIdentity();
259   t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
260   VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
261         * (t21.prescale(v21.cwiseInverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
262 
263   // Transform - new API
264   // 3D
265   t0.setIdentity();
266   t0.rotate(q1).scale(v0).translate(v0);
267   // mat * aligned scaling and mat * translation
268   t1 = (Matrix3(q1) * AlignedScaling3(v0)) * Translation3(v0);
269   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
270   t1 = (Matrix3(q1) * Eigen::Scaling(v0)) * Translation3(v0);
271   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
272   t1 = (q1 * Eigen::Scaling(v0)) * Translation3(v0);
273   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
274   // mat * transformation and aligned scaling * translation
275   t1 = Matrix3(q1) * (AlignedScaling3(v0) * Translation3(v0));
276   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
277 
278 
279   t0.setIdentity();
280   t0.scale(s0).translate(v0);
281   t1 = Eigen::Scaling(s0) * Translation3(v0);
282   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
283   t0.prescale(s0);
284   t1 = Eigen::Scaling(s0) * t1;
285   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
286 
287   t0 = t3;
288   t0.scale(s0);
289   t1 = t3 * Eigen::Scaling(s0,s0,s0);
290   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
291   t0.prescale(s0);
292   t1 = Eigen::Scaling(s0,s0,s0) * t1;
293   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
294 
295 
296   t0.setIdentity();
297   t0.prerotate(q1).prescale(v0).pretranslate(v0);
298   // translation * aligned scaling and transformation * mat
299   t1 = (Translation3(v0) * AlignedScaling3(v0)) * Transform3(q1);
300   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
301   // scaling * mat and translation * mat
302   t1 = Translation3(v0) * (AlignedScaling3(v0) * Transform3(q1));
303   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
304 
305   t0.setIdentity();
306   t0.scale(v0).translate(v0).rotate(q1);
307   // translation * mat and aligned scaling * transformation
308   t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
309   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
310   // transformation * aligned scaling
311   t0.scale(v0);
312   t1 *= AlignedScaling3(v0);
313   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
314   // transformation * translation
315   t0.translate(v0);
316   t1 = t1 * Translation3(v0);
317   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
318   // translation * transformation
319   t0.pretranslate(v0);
320   t1 = Translation3(v0) * t1;
321   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
322 
323   // transform * quaternion
324   t0.rotate(q1);
325   t1 = t1 * q1;
326   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
327 
328   // translation * quaternion
329   t0.translate(v1).rotate(q1);
330   t1 = t1 * (Translation3(v1) * q1);
331   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
332 
333   // aligned scaling * quaternion
334   t0.scale(v1).rotate(q1);
335   t1 = t1 * (AlignedScaling3(v1) * q1);
336   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
337 
338   // quaternion * transform
339   t0.prerotate(q1);
340   t1 = q1 * t1;
341   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
342 
343   // quaternion * translation
344   t0.rotate(q1).translate(v1);
345   t1 = t1 * (q1 * Translation3(v1));
346   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
347 
348   // quaternion * aligned scaling
349   t0.rotate(q1).scale(v1);
350   t1 = t1 * (q1 * AlignedScaling3(v1));
351   VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
352 
353   // test transform inversion
354   t0.setIdentity();
355   t0.translate(v0);
356   t0.linear().setRandom();
357   Matrix4 t044 = Matrix4::Zero();
358   t044(3,3) = 1;
359   t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
360   VERIFY_IS_APPROX(t0.inverse(Affine).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
361   t0.setIdentity();
362   t0.translate(v0).rotate(q1);
363   t044 = Matrix4::Zero();
364   t044(3,3) = 1;
365   t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
366   VERIFY_IS_APPROX(t0.inverse(Isometry).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
367 
368   Matrix3 mat_rotation, mat_scaling;
369   t0.setIdentity();
370   t0.translate(v0).rotate(q1).scale(v1);
371   t0.computeRotationScaling(&mat_rotation, &mat_scaling);
372   VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
373   VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
374   VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
375   t0.computeScalingRotation(&mat_scaling, &mat_rotation);
376   VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
377   VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
378   VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
379 
380   // test casting
381   Transform<float,3,Mode> t1f = t1.template cast<float>();
382   VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
383   Transform<double,3,Mode> t1d = t1.template cast<double>();
384   VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
385 
386   Translation3 tr1(v0);
387   Translation<float,3> tr1f = tr1.template cast<float>();
388   VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
389   Translation<double,3> tr1d = tr1.template cast<double>();
390   VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
391 
392   AngleAxis<float> aa1f = aa1.template cast<float>();
393   VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
394   AngleAxis<double> aa1d = aa1.template cast<double>();
395   VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
396 
397   Rotation2D<Scalar> r2d1(internal::random<Scalar>());
398   Rotation2D<float> r2d1f = r2d1.template cast<float>();
399   VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
400   Rotation2D<double> r2d1d = r2d1.template cast<double>();
401   VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
402 
403   t20 = Translation2(v20) * (Rotation2D<Scalar>(s0) * Scaling(s0));
404   t21 = Translation2(v20) * Rotation2D<Scalar>(s0) * Scaling(s0);
405   VERIFY_IS_APPROX(t20,t21);
406 }
407 
transform_alignment()408 template<typename Scalar> void transform_alignment()
409 {
410   typedef Transform<Scalar,3,Projective,AutoAlign> Projective3a;
411   typedef Transform<Scalar,3,Projective,DontAlign> Projective3u;
412 
413   EIGEN_ALIGN16 Scalar array1[16];
414   EIGEN_ALIGN16 Scalar array2[16];
415   EIGEN_ALIGN16 Scalar array3[16+1];
416   Scalar* array3u = array3+1;
417 
418   Projective3a *p1 = ::new(reinterpret_cast<void*>(array1)) Projective3a;
419   Projective3u *p2 = ::new(reinterpret_cast<void*>(array2)) Projective3u;
420   Projective3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Projective3u;
421 
422   p1->matrix().setRandom();
423   *p2 = *p1;
424   *p3 = *p1;
425 
426   VERIFY_IS_APPROX(p1->matrix(), p2->matrix());
427   VERIFY_IS_APPROX(p1->matrix(), p3->matrix());
428 
429   VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
430 
431   #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
432   if(internal::packet_traits<Scalar>::Vectorizable)
433     VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a));
434   #endif
435 }
436 
transform_products()437 template<typename Scalar, int Dim, int Options> void transform_products()
438 {
439   typedef Matrix<Scalar,Dim+1,Dim+1> Mat;
440   typedef Transform<Scalar,Dim,Projective,Options> Proj;
441   typedef Transform<Scalar,Dim,Affine,Options> Aff;
442   typedef Transform<Scalar,Dim,AffineCompact,Options> AffC;
443 
444   Proj p; p.matrix().setRandom();
445   Aff a; a.linear().setRandom(); a.translation().setRandom();
446   AffC ac = a;
447 
448   Mat p_m(p.matrix()), a_m(a.matrix());
449 
450   VERIFY_IS_APPROX((p*p).matrix(), p_m*p_m);
451   VERIFY_IS_APPROX((a*a).matrix(), a_m*a_m);
452   VERIFY_IS_APPROX((p*a).matrix(), p_m*a_m);
453   VERIFY_IS_APPROX((a*p).matrix(), a_m*p_m);
454   VERIFY_IS_APPROX((ac*a).matrix(), a_m*a_m);
455   VERIFY_IS_APPROX((a*ac).matrix(), a_m*a_m);
456   VERIFY_IS_APPROX((p*ac).matrix(), p_m*a_m);
457   VERIFY_IS_APPROX((ac*p).matrix(), a_m*p_m);
458 }
459 
test_geo_transformations()460 void test_geo_transformations()
461 {
462   for(int i = 0; i < g_repeat; i++) {
463     CALL_SUBTEST_1(( transformations<double,Affine,AutoAlign>() ));
464     CALL_SUBTEST_1(( non_projective_only<double,Affine,AutoAlign>() ));
465 
466     CALL_SUBTEST_2(( transformations<float,AffineCompact,AutoAlign>() ));
467     CALL_SUBTEST_2(( non_projective_only<float,AffineCompact,AutoAlign>() ));
468     CALL_SUBTEST_2(( transform_alignment<float>() ));
469 
470     CALL_SUBTEST_3(( transformations<double,Projective,AutoAlign>() ));
471     CALL_SUBTEST_3(( transformations<double,Projective,DontAlign>() ));
472     CALL_SUBTEST_3(( transform_alignment<double>() ));
473 
474     CALL_SUBTEST_4(( transformations<float,Affine,RowMajor|AutoAlign>() ));
475     CALL_SUBTEST_4(( non_projective_only<float,Affine,RowMajor>() ));
476 
477     CALL_SUBTEST_5(( transformations<double,AffineCompact,RowMajor|AutoAlign>() ));
478     CALL_SUBTEST_5(( non_projective_only<double,AffineCompact,RowMajor>() ));
479 
480     CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|AutoAlign>() ));
481     CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|DontAlign>() ));
482 
483 
484     CALL_SUBTEST_7(( transform_products<double,3,RowMajor|AutoAlign>() ));
485     CALL_SUBTEST_7(( transform_products<float,2,AutoAlign>() ));
486   }
487 }
488