1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <iostream>
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/Geometry>
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <bench/BenchTimer.h>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathusing namespace Eigen;
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathusing namespace std;
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Q>
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Q nlerp(const Q& a, const Q& b, typename Q::Scalar t)
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return Q((a.coeffs() * (1.0-t) + b.coeffs() * t).normalized());
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Q>
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Q slerp_eigen(const Q& a, const Q& b, typename Q::Scalar t)
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return a.slerp(t,b);
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Q>
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Q slerp_legacy(const Q& a, const Q& b, typename Q::Scalar t)
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Q::Scalar Scalar;
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static const Scalar one = Scalar(1) - dummy_precision<Scalar>();
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar d = a.dot(b);
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar absD = internal::abs(d);
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (absD>=one)
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return a;
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // theta is the angle between the 2 quaternions
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar theta = std::acos(absD);
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar sinTheta = internal::sin(theta);
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale1 = internal::sin( ( t * theta) ) / sinTheta;
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (d<0)
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale1 = -scale1;
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return Q(scale0 * a.coeffs() + scale1 * b.coeffs());
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Q>
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Q slerp_legacy_nlerp(const Q& a, const Q& b, typename Q::Scalar t)
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Q::Scalar Scalar;
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  static const Scalar one = Scalar(1) - epsilon<Scalar>();
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar d = a.dot(b);
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar absD = internal::abs(d);
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale0;
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale1;
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (absD>=one)
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale0 = Scalar(1) - t;
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale1 = t;
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // theta is the angle between the 2 quaternions
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar theta = std::acos(absD);
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar sinTheta = internal::sin(theta);
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale1 = internal::sin( ( t * theta) ) / sinTheta;
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if (d<0)
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      scale1 = -scale1;
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return Q(scale0 * a.coeffs() + scale1 * b.coeffs());
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T>
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathinline T sin_over_x(T x)
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (T(1) + x*x == T(1))
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return T(1);
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    return std::sin(x)/x;
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Q>
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Q slerp_rw(const Q& a, const Q& b, typename Q::Scalar t)
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Q::Scalar Scalar;
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar d = a.dot(b);
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar theta;
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (d<0.0)
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    theta = /*M_PI -*/ Scalar(2)*std::asin( (a.coeffs()+b.coeffs()).norm()/2 );
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    theta = Scalar(2)*std::asin( (a.coeffs()-b.coeffs()).norm()/2 );
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // theta is the angle between the 2 quaternions
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//   Scalar theta = std::acos(absD);
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar sinOverTheta = sin_over_x(theta);
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale0 = (Scalar(1)-t)*sin_over_x( ( Scalar(1) - t ) * theta) / sinOverTheta;
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale1 = t * sin_over_x( ( t * theta) ) / sinOverTheta;
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (d<0)
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale1 = -scale1;
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return Quaternion<Scalar>(scale0 * a.coeffs() + scale1 * b.coeffs());
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Q>
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathEIGEN_DONT_INLINE Q slerp_gael(const Q& a, const Q& b, typename Q::Scalar t)
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename Q::Scalar Scalar;
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar d = a.dot(b);
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar theta;
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//   theta = Scalar(2) * atan2((a.coeffs()-b.coeffs()).norm(),(a.coeffs()+b.coeffs()).norm());
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//   if (d<0.0)
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//     theta = M_PI-theta;
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (d<0.0)
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    theta = /*M_PI -*/ Scalar(2)*std::asin( (-a.coeffs()-b.coeffs()).norm()/2 );
121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    theta = Scalar(2)*std::asin( (a.coeffs()-b.coeffs()).norm()/2 );
123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale0;
126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Scalar scale1;
127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if(theta*theta-Scalar(6)==-Scalar(6))
128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale0 = Scalar(1) - t;
130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale1 = t;
131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Scalar sinTheta = std::sin(theta);
135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    scale1 = internal::sin( ( t * theta) ) / sinTheta;
137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    if (d<0)
138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      scale1 = -scale1;
139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return Quaternion<Scalar>(scale0 * a.coeffs() + scale1 * b.coeffs());
142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathint main()
145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef double RefScalar;
147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef float TestScalar;
148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Quaternion<RefScalar>  Qd;
150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef Quaternion<TestScalar> Qf;
151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  unsigned int g_seed = (unsigned int) time(NULL);
153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  std::cout << g_seed << "\n";
154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//   g_seed = 1259932496;
155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  srand(g_seed);
156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<RefScalar,Dynamic,1> maxerr(7);
158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  maxerr.setZero();
159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Matrix<RefScalar,Dynamic,1> avgerr(7);
161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  avgerr.setZero();
162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  cout << "double=>float=>double       nlerp        eigen        legacy(snap)         legacy(nlerp)        rightway         gael's criteria\n";
164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int rep = 100;
166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int iters = 40;
167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for (int w=0; w<rep; ++w)
168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Qf a, b;
170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.coeffs().setRandom();
171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    a.normalize();
172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    b.coeffs().setRandom();
173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    b.normalize();
174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Qf c[6];
176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Qd ar(a.cast<RefScalar>());
178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Qd br(b.cast<RefScalar>());
179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    Qd cr;
180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    cout.precision(8);
184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    cout << std::scientific;
185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (int i=0; i<iters; ++i)
186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      RefScalar t = 0.65;
188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      cr = slerp_rw(ar,br,t);
189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Qf refc = cr.cast<TestScalar>();
191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c[0] = nlerp(a,b,t);
192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c[1] = slerp_eigen(a,b,t);
193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c[2] = slerp_legacy(a,b,t);
194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c[3] = slerp_legacy_nlerp(a,b,t);
195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c[4] = slerp_rw(a,b,t);
196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      c[5] = slerp_gael(a,b,t);
197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      VectorXd err(7);
199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      err[0] = (cr.coeffs()-refc.cast<RefScalar>().coeffs()).norm();
200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//       std::cout << err[0] << "    ";
201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for (int k=0; k<6; ++k)
202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        err[k+1] = (c[k].coeffs()-refc.coeffs()).norm();
204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//         std::cout << err[k+1] << "    ";
205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      maxerr = maxerr.cwise().max(err);
207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      avgerr += err;
208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//       std::cout << "\n";
209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      b = cr.cast<TestScalar>();
210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      br = cr;
211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//     std::cout << "\n";
213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  avgerr /= RefScalar(rep*iters);
215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  cout << "\n\nAccuracy:\n"
216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath       << "  max: " << maxerr.transpose() << "\n";
217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  cout << "  avg: " << avgerr.transpose() << "\n";
218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // perf bench
220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Quaternionf a,b;
221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  a.coeffs().setRandom();
222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  a.normalize();
223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  b.coeffs().setRandom();
224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  b.normalize();
225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  //b = a;
226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  float s = 0.65;
227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  #define BENCH(FUNC) {\
229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    BenchTimer t; \
230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for(int k=0; k<2; ++k) {\
231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      t.start(); \
232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      for(int i=0; i<1000000; ++i) \
233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        FUNC(a,b,s); \
234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      t.stop(); \
235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    } \
236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    cout << "  " << #FUNC << " => \t " << t.value() << "s\n"; \
237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  cout << "\nSpeed:\n" << std::fixed;
240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  BENCH(nlerp);
241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  BENCH(slerp_eigen);
242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  BENCH(slerp_legacy);
243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  BENCH(slerp_legacy_nlerp);
244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  BENCH(slerp_rw);
245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  BENCH(slerp_gael);
246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
248