blob: 4d93533efcfcdbc40595120c2d621e9d328f6b7d [file]
#include <benchmark/benchmark.h>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <Eigen/SVD>
using namespace Eigen;
// ============================================================================
// Quaternion operations
// ============================================================================
template <typename Scalar>
static void BM_QuatSlerp(benchmark::State& state) {
Quaternion<Scalar> q0 = Quaternion<Scalar>::UnitRandom();
Quaternion<Scalar> q1 = Quaternion<Scalar>::UnitRandom();
Quaternion<Scalar> r;
Scalar t = Scalar(0.5);
for (auto _ : state) {
r = q0.slerp(t, q1);
benchmark::DoNotOptimize(r.coeffs().data());
}
}
template <typename Scalar>
static void BM_QuatRotateVec(benchmark::State& state) {
Quaternion<Scalar> q = Quaternion<Scalar>::UnitRandom();
Matrix<Scalar, 3, 1> v = Matrix<Scalar, 3, 1>::Random();
for (auto _ : state) {
v = q * v;
benchmark::DoNotOptimize(v.data());
}
}
template <typename Scalar>
static void BM_QuatNormalize(benchmark::State& state) {
Quaternion<Scalar> q(Scalar(1.1), Scalar(2.2), Scalar(3.3), Scalar(4.4));
for (auto _ : state) {
q.normalize();
benchmark::DoNotOptimize(q.coeffs().data());
}
}
template <typename Scalar>
static void BM_QuatInverse(benchmark::State& state) {
Quaternion<Scalar> q = Quaternion<Scalar>::UnitRandom();
Quaternion<Scalar> r;
for (auto _ : state) {
r = q.inverse();
benchmark::DoNotOptimize(r.coeffs().data());
}
}
template <typename Scalar>
static void BM_QuatToRotationMatrix(benchmark::State& state) {
Quaternion<Scalar> q = Quaternion<Scalar>::UnitRandom();
Matrix<Scalar, 3, 3> m;
for (auto _ : state) {
m = q.toRotationMatrix();
benchmark::DoNotOptimize(m.data());
}
}
template <typename Scalar>
static void BM_QuatFromRotationMatrix(benchmark::State& state) {
Quaternion<Scalar> q = Quaternion<Scalar>::UnitRandom();
Matrix<Scalar, 3, 3> m = q.toRotationMatrix();
for (auto _ : state) {
q = m;
benchmark::DoNotOptimize(q.coeffs().data());
}
}
template <typename Scalar>
static void BM_QuatAngularDistance(benchmark::State& state) {
Quaternion<Scalar> q0 = Quaternion<Scalar>::UnitRandom();
Quaternion<Scalar> q1 = Quaternion<Scalar>::UnitRandom();
Scalar d;
for (auto _ : state) {
d = q0.angularDistance(q1);
benchmark::DoNotOptimize(d);
}
}
template <typename Scalar>
static void BM_QuatSetFromTwoVectors(benchmark::State& state) {
Matrix<Scalar, 3, 1> v0 = Matrix<Scalar, 3, 1>::Random().normalized();
Matrix<Scalar, 3, 1> v1 = Matrix<Scalar, 3, 1>::Random().normalized();
Quaternion<Scalar> q;
for (auto _ : state) {
q.setFromTwoVectors(v0, v1);
benchmark::DoNotOptimize(q.coeffs().data());
}
}
// ============================================================================
// AngleAxis operations
// ============================================================================
template <typename Scalar>
static void BM_AngleAxisToRotationMatrix(benchmark::State& state) {
AngleAxis<Scalar> aa(Scalar(1.0), Matrix<Scalar, 3, 1>::UnitX());
Matrix<Scalar, 3, 3> m;
for (auto _ : state) {
m = aa.toRotationMatrix();
benchmark::DoNotOptimize(m.data());
}
}
template <typename Scalar>
static void BM_AngleAxisFromRotationMatrix(benchmark::State& state) {
Quaternion<Scalar> q = Quaternion<Scalar>::UnitRandom();
Matrix<Scalar, 3, 3> m = q.toRotationMatrix();
AngleAxis<Scalar> aa;
for (auto _ : state) {
aa = m;
benchmark::DoNotOptimize(aa);
}
}
template <typename Scalar>
static void BM_AngleAxisRotateVec(benchmark::State& state) {
AngleAxis<Scalar> aa(Scalar(1.0), Matrix<Scalar, 3, 1>::Random().normalized());
Matrix<Scalar, 3, 1> v = Matrix<Scalar, 3, 1>::Random();
for (auto _ : state) {
v = aa * v;
benchmark::DoNotOptimize(v.data());
}
}
// ============================================================================
// Rotation2D operations
// ============================================================================
template <typename Scalar>
static void BM_Rotation2DRotateVec(benchmark::State& state) {
Rotation2D<Scalar> r(Scalar(0.5));
Matrix<Scalar, 2, 1> v = Matrix<Scalar, 2, 1>::Random();
for (auto _ : state) {
v = r * v;
benchmark::DoNotOptimize(v.data());
}
}
template <typename Scalar>
static void BM_Rotation2DSlerp(benchmark::State& state) {
Rotation2D<Scalar> r0(Scalar(0.1)), r1(Scalar(2.5));
Rotation2D<Scalar> r;
for (auto _ : state) {
r = r0.slerp(Scalar(0.5), r1);
benchmark::DoNotOptimize(r);
}
}
// ============================================================================
// Transform inverse
// ============================================================================
template <typename Scalar, int Mode>
static void BM_TransformInverse(benchmark::State& state) {
typedef Transform<Scalar, 3, Mode> Trans;
Trans t;
t.setIdentity();
t.rotate(Quaternion<Scalar>::UnitRandom());
t.translate(Matrix<Scalar, 3, 1>::Random());
Trans r;
for (auto _ : state) {
r = t.inverse();
benchmark::DoNotOptimize(r.data());
}
}
// ============================================================================
// Euler angles
// ============================================================================
template <typename Scalar>
static void BM_EulerAnglesExtract(benchmark::State& state) {
Quaternion<Scalar> q = Quaternion<Scalar>::UnitRandom();
Matrix<Scalar, 3, 3> m = q.toRotationMatrix();
Matrix<Scalar, 3, 1> ea;
for (auto _ : state) {
ea = m.canonicalEulerAngles(0, 1, 2);
benchmark::DoNotOptimize(ea.data());
}
}
// ============================================================================
// Cross product
// ============================================================================
template <typename Scalar>
static void BM_CrossProduct(benchmark::State& state) {
Matrix<Scalar, 3, 1> a = Matrix<Scalar, 3, 1>::Random();
Matrix<Scalar, 3, 1> b = Matrix<Scalar, 3, 1>::Random();
Matrix<Scalar, 3, 1> c;
for (auto _ : state) {
c = a.cross(b);
benchmark::DoNotOptimize(c.data());
}
}
template <typename Scalar>
static void BM_UnitOrthogonal(benchmark::State& state) {
Matrix<Scalar, 3, 1> v = Matrix<Scalar, 3, 1>::Random();
Matrix<Scalar, 3, 1> r;
for (auto _ : state) {
r = v.unitOrthogonal();
benchmark::DoNotOptimize(r.data());
}
}
// ============================================================================
// AlignedBox operations
// ============================================================================
template <typename Scalar>
static void BM_AlignedBoxContains(benchmark::State& state) {
AlignedBox<Scalar, 3> box(Matrix<Scalar, 3, 1>(-1, -1, -1), Matrix<Scalar, 3, 1>(1, 1, 1));
Matrix<Scalar, 3, 1> p = Matrix<Scalar, 3, 1>::Random();
bool result;
for (auto _ : state) {
result = box.contains(p);
benchmark::DoNotOptimize(result);
}
}
template <typename Scalar>
static void BM_AlignedBoxIntersects(benchmark::State& state) {
AlignedBox<Scalar, 3> box1(Matrix<Scalar, 3, 1>(-1, -1, -1), Matrix<Scalar, 3, 1>(1, 1, 1));
AlignedBox<Scalar, 3> box2(Matrix<Scalar, 3, 1>(0, 0, 0), Matrix<Scalar, 3, 1>(2, 2, 2));
bool result;
for (auto _ : state) {
result = box1.intersects(box2);
benchmark::DoNotOptimize(result);
}
}
template <typename Scalar>
static void BM_AlignedBoxTransform(benchmark::State& state) {
AlignedBox<Scalar, 3> box(Matrix<Scalar, 3, 1>(-1, -1, -1), Matrix<Scalar, 3, 1>(1, 1, 1));
Transform<Scalar, 3, Isometry> t;
t.setIdentity();
t.rotate(Quaternion<Scalar>::UnitRandom());
t.translate(Matrix<Scalar, 3, 1>::Random());
for (auto _ : state) {
AlignedBox<Scalar, 3> result = box.transformed(t);
benchmark::DoNotOptimize(result);
}
}
// ============================================================================
// Hyperplane / ParametrizedLine
// ============================================================================
template <typename Scalar>
static void BM_HyperplaneSignedDistance(benchmark::State& state) {
Hyperplane<Scalar, 3> plane = Hyperplane<Scalar, 3>::Through(
Matrix<Scalar, 3, 1>(1, 0, 0), Matrix<Scalar, 3, 1>(0, 1, 0), Matrix<Scalar, 3, 1>(0, 0, 1));
Matrix<Scalar, 3, 1> p = Matrix<Scalar, 3, 1>::Random();
Scalar d;
for (auto _ : state) {
d = plane.signedDistance(p);
benchmark::DoNotOptimize(d);
}
}
template <typename Scalar>
static void BM_LinePointDistance(benchmark::State& state) {
ParametrizedLine<Scalar, 3> line(Matrix<Scalar, 3, 1>::Zero(), Matrix<Scalar, 3, 1>::UnitX());
Matrix<Scalar, 3, 1> p = Matrix<Scalar, 3, 1>::Random();
Scalar d;
for (auto _ : state) {
d = line.distance(p);
benchmark::DoNotOptimize(d);
}
}
template <typename Scalar>
static void BM_LinePlaneIntersection(benchmark::State& state) {
ParametrizedLine<Scalar, 3> line(Matrix<Scalar, 3, 1>::Zero(), Matrix<Scalar, 3, 1>::UnitZ());
Hyperplane<Scalar, 3> plane(Matrix<Scalar, 3, 1>::UnitZ(), Scalar(-5));
Scalar t;
for (auto _ : state) {
t = line.intersectionParameter(plane);
benchmark::DoNotOptimize(t);
}
}
// ============================================================================
// Umeyama
// ============================================================================
template <typename Scalar, int Dim>
static void BM_Umeyama(benchmark::State& state) {
const int n = state.range(0);
Matrix<Scalar, Dim, Dynamic> src = Matrix<Scalar, Dim, Dynamic>::Random(Dim, n);
// Apply a known transform
Matrix<Scalar, Dim, Dim> R = Quaternion<Scalar>::UnitRandom().toRotationMatrix();
Matrix<Scalar, Dim, 1> t = Matrix<Scalar, Dim, 1>::Random() * Scalar(10);
Matrix<Scalar, Dim, Dynamic> dst = (R * src).colwise() + t;
for (auto _ : state) {
auto T = umeyama(src, dst);
benchmark::DoNotOptimize(T);
}
}
// ============================================================================
// Registration
// ============================================================================
// Quaternion
BENCHMARK(BM_QuatSlerp<float>);
BENCHMARK(BM_QuatSlerp<double>);
BENCHMARK(BM_QuatRotateVec<float>);
BENCHMARK(BM_QuatRotateVec<double>);
BENCHMARK(BM_QuatNormalize<float>);
BENCHMARK(BM_QuatNormalize<double>);
BENCHMARK(BM_QuatInverse<float>);
BENCHMARK(BM_QuatInverse<double>);
BENCHMARK(BM_QuatToRotationMatrix<float>);
BENCHMARK(BM_QuatToRotationMatrix<double>);
BENCHMARK(BM_QuatFromRotationMatrix<float>);
BENCHMARK(BM_QuatFromRotationMatrix<double>);
BENCHMARK(BM_QuatAngularDistance<float>);
BENCHMARK(BM_QuatAngularDistance<double>);
BENCHMARK(BM_QuatSetFromTwoVectors<float>);
BENCHMARK(BM_QuatSetFromTwoVectors<double>);
// AngleAxis
BENCHMARK(BM_AngleAxisToRotationMatrix<float>);
BENCHMARK(BM_AngleAxisToRotationMatrix<double>);
BENCHMARK(BM_AngleAxisFromRotationMatrix<float>);
BENCHMARK(BM_AngleAxisFromRotationMatrix<double>);
BENCHMARK(BM_AngleAxisRotateVec<float>);
BENCHMARK(BM_AngleAxisRotateVec<double>);
// Rotation2D
BENCHMARK(BM_Rotation2DRotateVec<float>);
BENCHMARK(BM_Rotation2DRotateVec<double>);
BENCHMARK(BM_Rotation2DSlerp<float>);
BENCHMARK(BM_Rotation2DSlerp<double>);
// Transform inverse
BENCHMARK(BM_TransformInverse<float, Isometry>);
BENCHMARK(BM_TransformInverse<float, Affine>);
BENCHMARK(BM_TransformInverse<double, Isometry>);
BENCHMARK(BM_TransformInverse<double, Affine>);
// Euler angles
BENCHMARK(BM_EulerAnglesExtract<float>);
BENCHMARK(BM_EulerAnglesExtract<double>);
// Cross product & orthogonal
BENCHMARK(BM_CrossProduct<float>);
BENCHMARK(BM_CrossProduct<double>);
BENCHMARK(BM_UnitOrthogonal<float>);
BENCHMARK(BM_UnitOrthogonal<double>);
// AlignedBox
BENCHMARK(BM_AlignedBoxContains<float>);
BENCHMARK(BM_AlignedBoxContains<double>);
BENCHMARK(BM_AlignedBoxIntersects<float>);
BENCHMARK(BM_AlignedBoxIntersects<double>);
BENCHMARK(BM_AlignedBoxTransform<float>);
BENCHMARK(BM_AlignedBoxTransform<double>);
// Hyperplane / ParametrizedLine
BENCHMARK(BM_HyperplaneSignedDistance<float>);
BENCHMARK(BM_HyperplaneSignedDistance<double>);
BENCHMARK(BM_LinePointDistance<float>);
BENCHMARK(BM_LinePointDistance<double>);
BENCHMARK(BM_LinePlaneIntersection<float>);
BENCHMARK(BM_LinePlaneIntersection<double>);
// Umeyama
BENCHMARK(BM_Umeyama<float, 3>)->Arg(10)->Arg(100)->Arg(1000);
BENCHMARK(BM_Umeyama<double, 3>)->Arg(10)->Arg(100)->Arg(1000);