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