// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2025 Rasmus Munk Larsen <rmlarsen@google.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

// Tests for Geometry module classes that lack dedicated test coverage:
//   - AngleAxis edge cases
//   - Rotation2D standalone tests
//   - Translation standalone tests
//   - Scaling standalone tests
//   - Quaternion fromRotationMatrix with non-orthogonal input
//   - Quaternion slerp edge cases
//   - Umeyama degenerate input
//   - Transform shear ground truth

#include "main.h"
#include <Eigen/Geometry>
#include <Eigen/LU>
#include <Eigen/SVD>

template <typename Scalar>
void angleaxis_edge_cases() {
  typedef Matrix<Scalar, 3, 1> Vector3;
  typedef Matrix<Scalar, 3, 3> Matrix3;
  typedef AngleAxis<Scalar> AngleAxisx;
  typedef Quaternion<Scalar> Quaternionx;

  Scalar eps = test_precision<Scalar>();

  // Identity rotation (angle = 0)
  {
    AngleAxisx aa(Scalar(0), Vector3::UnitZ());
    Matrix3 m = aa.toRotationMatrix();
    VERIFY_IS_APPROX(m, Matrix3::Identity());
    // Verify orthogonality: R^T * R = I
    VERIFY_IS_APPROX(m.transpose() * m, Matrix3::Identity());
    VERIFY_IS_APPROX(m.determinant(), Scalar(1));
    Quaternionx q(aa);
    VERIFY_IS_APPROX(q.toRotationMatrix(), Matrix3::Identity());
    VERIFY_IS_APPROX(q.norm(), Scalar(1));
  }

  // 180-degree rotation around each axis
  {
    for (int axis = 0; axis < 3; ++axis) {
      Vector3 ax = Vector3::Zero();
      ax(axis) = Scalar(1);
      AngleAxisx aa(Scalar(EIGEN_PI), ax);
      Matrix3 m = aa.toRotationMatrix();
      // Should be its own inverse
      VERIFY_IS_APPROX(m * m, Matrix3::Identity());
      // Verify orthogonality
      VERIFY_IS_APPROX(m.transpose() * m, Matrix3::Identity());
      VERIFY_IS_APPROX(m.determinant(), Scalar(1));
      // Diagonal entry for the rotation axis should be +1, others -1
      VERIFY_IS_APPROX(m(axis, axis), Scalar(1));
      for (int j = 0; j < 3; ++j) {
        if (j != axis) VERIFY_IS_APPROX(m(j, j), Scalar(-1));
      }
    }
  }

  // Very small angle: verify Rodrigues formula accuracy
  {
    Scalar tiny = Scalar(10) * NumTraits<Scalar>::epsilon();
    AngleAxisx aa(tiny, Vector3::UnitX());
    Matrix3 m = aa.toRotationMatrix();
    VERIFY((m - Matrix3::Identity()).norm() < Scalar(4) * tiny);
    // Orthogonality should hold to machine precision even for tiny angles
    VERIFY_IS_APPROX(m.transpose() * m, Matrix3::Identity());
    VERIFY_IS_APPROX(m.determinant(), Scalar(1));
    // Round-trip through quaternion
    Quaternionx q(aa);
    AngleAxisx aa2(q);
    VERIFY(abs(aa2.angle()) < Scalar(4) * tiny);
  }

  // Round-trip: AngleAxis -> Matrix -> AngleAxis
  {
    Scalar a = internal::random<Scalar>(Scalar(0.1), Scalar(EIGEN_PI) - Scalar(0.1));
    Vector3 axis = Vector3::Random().normalized();
    AngleAxisx aa(a, axis);
    Matrix3 m = aa.toRotationMatrix();
    VERIFY_IS_APPROX(m.transpose() * m, Matrix3::Identity());
    VERIFY_IS_APPROX(m.determinant(), Scalar(1));
    AngleAxisx aa2;
    aa2.fromRotationMatrix(m);
    VERIFY_IS_APPROX(aa.toRotationMatrix(), aa2.toRotationMatrix());
    // Verify angle is preserved
    VERIFY(abs(aa2.angle() - a) < eps);
  }

  // Round-trip for near-180-degree rotation
  {
    Scalar a = Scalar(EIGEN_PI) - Scalar(10) * NumTraits<Scalar>::epsilon();
    Vector3 axis = Vector3::Random().normalized();
    AngleAxisx aa(a, axis);
    Matrix3 m = aa.toRotationMatrix();
    VERIFY_IS_APPROX(m.transpose() * m, Matrix3::Identity());
    VERIFY_IS_APPROX(m.determinant(), Scalar(1));
    AngleAxisx aa2(m);
    // The rotation should be equivalent even if axis flips sign
    VERIFY_IS_APPROX(aa.toRotationMatrix(), aa2.toRotationMatrix());
  }

  // Accessors
  {
    Vector3 axis = Vector3::Random().normalized();
    Scalar angle = internal::random<Scalar>(Scalar(-EIGEN_PI), Scalar(EIGEN_PI));
    AngleAxisx aa(angle, axis);
    VERIFY_IS_APPROX(aa.angle(), angle);
    VERIFY_IS_APPROX(aa.axis(), axis);

    // Mutable accessors
    aa.angle() = Scalar(1);
    aa.axis() = Vector3::UnitZ();
    VERIFY_IS_APPROX(aa.angle(), Scalar(1));
    VERIFY_IS_APPROX(aa.axis(), Vector3::UnitZ());
  }

  // inverse
  {
    Scalar a = internal::random<Scalar>(Scalar(0.1), Scalar(EIGEN_PI));
    Vector3 axis = Vector3::Random().normalized();
    AngleAxisx aa(a, axis);
    VERIFY_IS_APPROX((aa * aa.inverse()).toRotationMatrix(), Matrix3::Identity());
  }

  // isApprox
  {
    Scalar a = internal::random<Scalar>(Scalar(0.1), Scalar(EIGEN_PI));
    Vector3 axis = Vector3::Random().normalized();
    AngleAxisx aa1(a, axis);
    AngleAxisx aa2(a + eps / Scalar(10), axis);
    VERIFY(aa1.isApprox(aa2, eps));
  }

  // Quaternion round-trip: AngleAxis -> Quaternion -> AngleAxis
  {
    Scalar a = internal::random<Scalar>(Scalar(0.1), Scalar(EIGEN_PI) - Scalar(0.1));
    Vector3 axis = Vector3::Random().normalized();
    AngleAxisx aa(a, axis);
    Quaternionx q(aa);
    VERIFY_IS_APPROX(q.norm(), Scalar(1));
    AngleAxisx aa2(q);
    VERIFY(abs(aa2.angle() - a) < eps);
    // Axis should agree (possibly with sign flip for angle > pi)
    VERIFY(aa2.axis().isApprox(axis, eps) || aa2.axis().isApprox(-axis, eps));
  }
}

template <typename Scalar>
void rotation2d_standalone() {
  typedef Matrix<Scalar, 2, 1> Vector2;
  typedef Matrix<Scalar, 2, 2> Matrix2;
  typedef Rotation2D<Scalar> Rotation2Dx;

  Scalar eps = test_precision<Scalar>();

  // Construction and basic properties
  {
    Rotation2Dx r(Scalar(0));
    VERIFY_IS_APPROX(r.toRotationMatrix(), Matrix2::Identity());
  }

  // 90-degree rotation
  {
    Rotation2Dx r(Scalar(EIGEN_PI) / Scalar(2));
    Vector2 v(1, 0);
    Vector2 rv = r * v;
    VERIFY_IS_APPROX(rv, Vector2(0, 1));
  }

  // 180-degree rotation
  {
    Rotation2Dx r(Scalar(EIGEN_PI));
    Vector2 v(1, 0);
    Vector2 rv = r * v;
    VERIFY_IS_APPROX(rv, Vector2(-1, 0));
  }

  // inverse
  {
    Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
    Rotation2Dx r(a);
    VERIFY_IS_APPROX((r * r.inverse()).toRotationMatrix(), Matrix2::Identity());
  }

  // composition
  {
    Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
    Scalar b = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
    Rotation2Dx ra(a), rb(b);
    VERIFY_IS_APPROX((ra * rb).toRotationMatrix(), ra.toRotationMatrix() * rb.toRotationMatrix());
  }

  // fromRotationMatrix round-trip: angle should agree to tight tolerance
  {
    Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
    Rotation2Dx r(a);
    Matrix2 m = r.toRotationMatrix();
    // Verify orthogonality
    VERIFY_IS_APPROX(m.transpose() * m, Matrix2::Identity());
    VERIFY_IS_APPROX(m.determinant(), Scalar(1));
    Rotation2Dx r2(m);
    // Angles should agree mod 2*pi. Use rotation matrices for exact comparison.
    VERIFY_IS_APPROX(r2.toRotationMatrix(), r.toRotationMatrix());
  }

  // slerp at t=0.5 of inverse should give ~0 or ~pi
  {
    Scalar a = internal::random<Scalar>(Scalar(0.1), Scalar(EIGEN_PI) / Scalar(2));
    Rotation2Dx r(a);
    Rotation2Dx half = r.slerp(Scalar(0.5), r.inverse());
    // The midpoint between a rotation and its inverse via shortest path should be ~0 or ~pi
    Scalar halfAngle = half.smallestAngle();
    VERIFY(abs(halfAngle) < eps || abs(abs(halfAngle) - Scalar(EIGEN_PI)) < eps);
  }

  // Rotation2D slerp interpolation: verify linearity of angle
  {
    Scalar a0 = internal::random<Scalar>(Scalar(-EIGEN_PI), Scalar(EIGEN_PI));
    Scalar a1 = a0 + internal::random<Scalar>(Scalar(0.1), Scalar(1.0));
    Rotation2Dx r0(a0), r1(a1);
    Scalar t = Scalar(0.3);
    Rotation2Dx rt = r0.slerp(t, r1);
    // Slerp for 2D rotations is just linear interpolation of angle along shortest path.
    Scalar expected = a0 + t * Rotation2Dx(a1 - a0).smallestAngle();
    VERIFY(abs(Rotation2Dx(rt.angle() - expected).smallestAngle()) < eps);
  }

  // smallestAngle range
  for (int k = 0; k < 100; ++k) {
    Scalar a = internal::random<Scalar>(Scalar(-100), Scalar(100));
    Rotation2Dx r(a);
    VERIFY(r.smallestAngle() >= -Scalar(EIGEN_PI));
    VERIFY(r.smallestAngle() <= Scalar(EIGEN_PI));
    VERIFY(r.smallestPositiveAngle() >= Scalar(0));
    VERIFY(r.smallestPositiveAngle() <= Scalar(2) * Scalar(EIGEN_PI));
  }
}

template <typename Scalar>
void translation_standalone() {
  typedef Matrix<Scalar, 3, 1> Vector3;
  typedef Translation<Scalar, 3> Translation3;
  typedef Transform<Scalar, 3, Isometry> Isometry3;

  // Construction
  {
    Vector3 v(1, 2, 3);
    Translation3 t(v);
    VERIFY_IS_APPROX(t.vector(), v);

    Translation3 t2(Scalar(1), Scalar(2), Scalar(3));
    VERIFY_IS_APPROX(t.vector(), t2.vector());
  }

  // Identity
  {
    Translation3 t = Translation3::Identity();
    VERIFY_IS_APPROX(t.vector(), Vector3::Zero());
  }

  // Composition
  {
    Vector3 v1(1, 2, 3), v2(4, 5, 6);
    Translation3 t1(v1), t2(v2);
    Translation3 t3 = t1 * t2;
    VERIFY_IS_APPROX(t3.vector(), v1 + v2);
  }

  // Inverse
  {
    Vector3 v(1, 2, 3);
    Translation3 t(v);
    Translation3 tinv = t.inverse();
    VERIFY_IS_APPROX(tinv.vector(), -v);
    VERIFY_IS_APPROX((t * tinv).vector(), Vector3::Zero());
  }

  // Translation * vector (via transform)
  {
    Vector3 v(1, 2, 3), p(10, 20, 30);
    Translation3 t(v);
    VERIFY_IS_APPROX(t * p, v + p);
  }

  // Casting
  {
    Translation3 t(Vector3(1, 2, 3));
    Translation<float, 3> tf = t.template cast<float>();
    VERIFY_IS_APPROX(tf.template cast<Scalar>().vector(), t.vector());
  }

  // Convert to Isometry
  {
    Vector3 v(1, 2, 3);
    Translation3 t(v);
    Isometry3 iso(t);
    VERIFY_IS_APPROX(iso.translation(), v);
    typedef Matrix<Scalar, 3, 3> Matrix3;
    VERIFY_IS_APPROX(iso.linear(), Matrix3::Identity());
  }
}

template <typename Scalar>
void scaling_standalone() {
  typedef Matrix<Scalar, 3, 1> Vector3;
  typedef Translation<Scalar, 3> Translation3;
  typedef Transform<Scalar, 3, Affine> Affine3;
  typedef UniformScaling<Scalar> UniformScalingx;

  // UniformScaling construction
  {
    UniformScalingx s(Scalar(2));
    VERIFY_IS_APPROX(s.factor(), Scalar(2));
  }

  // UniformScaling * vector
  {
    UniformScalingx s(Scalar(3));
    Vector3 v(1, 2, 3);
    // UniformScaling * Translation
    Translation3 t(v);
    Affine3 result = s * t;
    VERIFY_IS_APPROX(result.translation(), v * Scalar(3));
  }

  // UniformScaling composition
  {
    UniformScalingx s1(Scalar(2)), s2(Scalar(3));
    UniformScalingx s3 = s1 * s2;
    VERIFY_IS_APPROX(s3.factor(), Scalar(6));
  }

  // UniformScaling inverse
  {
    UniformScalingx s(Scalar(4));
    UniformScalingx si = s.inverse();
    VERIFY_IS_APPROX(si.factor(), Scalar(1) / Scalar(4));
    VERIFY_IS_APPROX((s * si).factor(), Scalar(1));
  }

  // Scaling convenience functions
  {
    Scalar s = Scalar(3);
    auto su = Eigen::Scaling(s);
    VERIFY_IS_APPROX(su.factor(), s);

    Vector3 sv(1, 2, 3);
    auto sd = Eigen::Scaling(sv);
    VERIFY_IS_APPROX(Vector3(sd.diagonal()), sv);
  }
}

template <typename Scalar>
void quaternion_from_non_orthogonal_matrix() {
  typedef Matrix<Scalar, 3, 3> Matrix3;
  typedef Quaternion<Scalar> Quaternionx;

  // Slightly non-orthogonal matrix should not produce NaN
  {
    Matrix3 m = Matrix3::Identity();
    // Perturb to make slightly non-orthogonal
    m(0, 0) += Scalar(1e-6);
    m(1, 1) -= Scalar(1e-6);
    Quaternionx q(m);
    // Should not be NaN
    VERIFY(!(numext::isnan)(q.w()));
    VERIFY(!(numext::isnan)(q.x()));
    VERIFY(!(numext::isnan)(q.y()));
    VERIFY(!(numext::isnan)(q.z()));
    // Should still be approximately a rotation
    VERIFY(abs(q.norm() - Scalar(1)) < Scalar(0.01));
  }

  // Negative trace case with non-orthogonal matrix
  {
    // 180-degree rotation around Z axis, slightly perturbed
    Matrix3 m;
    m << Scalar(-1), Scalar(0), Scalar(0), Scalar(0), Scalar(-1), Scalar(0), Scalar(0), Scalar(0), Scalar(1);
    m(0, 0) += Scalar(1e-6);
    Quaternionx q(m);
    VERIFY(!(numext::isnan)(q.w()));
    VERIFY(!(numext::isnan)(q.x()));
    VERIFY(!(numext::isnan)(q.y()));
    VERIFY(!(numext::isnan)(q.z()));
  }

  // Matrix with trace very close to -1 (worst case for positive trace branch)
  {
    Matrix3 m;
    m << Scalar(-1), Scalar(0), Scalar(0), Scalar(0), Scalar(-0.5), Scalar(0), Scalar(0), Scalar(0), Scalar(-0.5);
    // trace = -2, negative trace path
    Quaternionx q(m);
    VERIFY(!(numext::isnan)(q.w()));
    VERIFY(!(numext::isnan)(q.x()));
  }

  // Verify graceful handling of arbitrary non-rotation matrices.
  // Shoemake's argmax-diagonal selection makes the sqrt argument non-negative
  // for any real matrix, but the numext::maxi guard provides additional safety.
  {
    Matrix3 m;
    m << Scalar(-0.4), Scalar(0.5), Scalar(0), Scalar(-0.5), Scalar(-0.4), Scalar(0), Scalar(0), Scalar(0),
        Scalar(-0.4);
    Quaternionx q(m);
    VERIFY(!(numext::isnan)(q.w()));
    VERIFY(!(numext::isnan)(q.x()));
    VERIFY(!(numext::isnan)(q.y()));
    VERIFY(!(numext::isnan)(q.z()));
  }
}

template <typename Scalar>
void quaternion_slerp_edge_cases() {
  typedef Quaternion<Scalar> Quaternionx;
  typedef AngleAxis<Scalar> AngleAxisx;
  typedef Matrix<Scalar, 3, 1> Vector3;
  typedef Matrix<Scalar, 3, 3> Matrix3;

  Scalar eps = test_precision<Scalar>();
  // The slerp formula preserves unit norm to O(epsilon^2) for unit inputs.
  Scalar tight = Scalar(32) * NumTraits<Scalar>::epsilon();

  // slerp with identical quaternions
  {
    Quaternionx q = Quaternionx::UnitRandom();
    Quaternionx r = q.slerp(Scalar(0.5), q);
    VERIFY_IS_APPROX(r.coeffs(), q.coeffs());
    VERIFY(abs(r.norm() - Scalar(1)) < tight);
  }

  // slerp at t=0 and t=1
  {
    Quaternionx q0 = Quaternionx::UnitRandom();
    Quaternionx q1 = Quaternionx::UnitRandom();
    Quaternionx r0 = q0.slerp(Scalar(0), q1);
    Quaternionx r1 = q0.slerp(Scalar(1), q1);
    VERIFY(abs(r0.norm() - Scalar(1)) < tight);
    VERIFY(abs(r1.norm() - Scalar(1)) < tight);
    VERIFY_IS_APPROX(r0.toRotationMatrix(), q0.toRotationMatrix());
    VERIFY_IS_APPROX(r1.toRotationMatrix(), q1.toRotationMatrix());
  }

  // slerp with antipodal quaternions (represent same rotation)
  {
    Quaternionx q = Quaternionx::UnitRandom();
    Quaternionx qn;
    qn.coeffs() = -q.coeffs();
    for (Scalar t = 0; t <= Scalar(1.001); t += Scalar(0.25)) {
      Quaternionx r = q.slerp(t, qn);
      VERIFY(abs(r.norm() - Scalar(1)) < tight);
      // Should stay at the same rotation
      VERIFY_IS_APPROX(r.toRotationMatrix(), q.toRotationMatrix());
    }
  }

  // slerp with 180-degree apart quaternions
  {
    Vector3 axis1 = Vector3::UnitX();
    Quaternionx q0(AngleAxisx(Scalar(0), axis1));
    Quaternionx q1(AngleAxisx(Scalar(EIGEN_PI), axis1));
    Quaternionx mid = q0.slerp(Scalar(0.5), q1);
    VERIFY(abs(mid.norm() - Scalar(1)) < tight);
    // Midpoint should be a 90-degree rotation
    AngleAxisx aa(mid);
    VERIFY(abs(aa.angle() - Scalar(EIGEN_PI) / Scalar(2)) < test_precision<Scalar>());
  }

  // slerp unit-norm preservation and rotation matrix orthogonality
  {
    Quaternionx q0 = Quaternionx::UnitRandom();
    Quaternionx q1 = Quaternionx::UnitRandom();
    for (Scalar t = 0; t <= Scalar(1.001); t += Scalar(0.05)) {
      Quaternionx r = q0.slerp(t, q1);
      VERIFY(abs(r.norm() - Scalar(1)) < tight);
      Matrix3 m = r.toRotationMatrix();
      VERIFY_IS_APPROX(m.transpose() * m, Matrix3::Identity());
      VERIFY_IS_APPROX(m.determinant(), Scalar(1));
    }
  }

  // slerp monotonicity: angle from q0 should increase monotonically
  {
    Quaternionx q0 = Quaternionx::UnitRandom();
    Quaternionx q1 = Quaternionx::UnitRandom();
    Scalar prev_angle = Scalar(0);
    for (Scalar t = Scalar(0); t <= Scalar(1.001); t += Scalar(0.05)) {
      Quaternionx r = q0.slerp(t, q1);
      Scalar angle = AngleAxisx(r * q0.inverse()).angle();
      if (angle > Scalar(EIGEN_PI)) angle = Scalar(2) * Scalar(EIGEN_PI) - angle;
      VERIFY(angle >= prev_angle - tight);
      prev_angle = angle;
    }
  }
}

template <typename Scalar>
void umeyama_degenerate() {
  typedef Matrix<Scalar, 3, Dynamic> Points3;
  typedef Matrix<Scalar, 3, 1> Vector3;
  typedef Matrix<Scalar, 3, 3> Matrix3;
  typedef Matrix<Scalar, 4, 4> Matrix4;

  // All source points identical
  {
    int n = 10;
    Points3 src(3, n);
    src.colwise() = Vector3(1, 2, 3);
    Points3 dst = Points3::Random(3, n);

    Matrix4 T = umeyama(src, dst);
    // Result should NOT be NaN
    VERIFY(!(numext::isnan)(T(0, 0)));
    VERIFY(!(numext::isnan)(T(0, 3)));
  }

  // All destination points identical
  {
    int n = 10;
    Points3 src = Points3::Random(3, n);
    Points3 dst(3, n);
    dst.colwise() = Vector3(4, 5, 6);

    Matrix4 T = umeyama(src, dst);
    VERIFY(!(numext::isnan)(T(0, 0)));
  }

  // Pure translation (no rotation or scaling)
  {
    int n = 20;
    Points3 src = Points3::Random(3, n);
    Vector3 offset(10, 20, 30);
    Points3 dst = src.colwise() + offset;

    Matrix4 T = umeyama(src, dst);
    // Translation should be recovered
    Vector3 t_recovered = T.template block<3, 1>(0, 3);
    VERIFY_IS_APPROX(t_recovered, offset);
    // Rotation should be identity
    Matrix3 R = T.template block<3, 3>(0, 0);
    VERIFY(R.isApprox(Matrix3::Identity(), test_precision<Scalar>()));
  }
}

template <typename Scalar>
void shear_ground_truth() {
  typedef Transform<Scalar, 2, Affine> Transform2;
  typedef Matrix<Scalar, 2, 1> Vector2;

  // Verify the actual matrix produced by shear()
  // Note: Eigen's shear(sx, sy) applies the matrix [[1, sy], [sx, 1]] to columns,
  // meaning sx controls the y-component shear and sy controls the x-component shear.
  {
    Transform2 t;
    t.setIdentity();
    t.shear(Scalar(2), Scalar(0));
    // After shear(2, 0), linear part should be [[1, 0], [2, 1]]
    VERIFY_IS_APPROX(t.linear()(0, 0), Scalar(1));
    VERIFY_IS_APPROX(t.linear()(0, 1), Scalar(0));
    VERIFY_IS_APPROX(t.linear()(1, 0), Scalar(2));
    VERIFY_IS_APPROX(t.linear()(1, 1), Scalar(1));
  }

  {
    Transform2 t;
    t.setIdentity();
    t.shear(Scalar(0), Scalar(3));
    // After shear(0, 3), linear part should be [[1, 3], [0, 1]]
    VERIFY_IS_APPROX(t.linear()(0, 0), Scalar(1));
    VERIFY_IS_APPROX(t.linear()(0, 1), Scalar(3));
    VERIFY_IS_APPROX(t.linear()(1, 0), Scalar(0));
    VERIFY_IS_APPROX(t.linear()(1, 1), Scalar(1));
  }

  // Verify shear on a point
  {
    Transform2 t;
    t.setIdentity();
    t.shear(Scalar(2), Scalar(3));
    Vector2 v(1, 0);
    Vector2 result = t.linear() * v;
    // [[1, 3], [2, 1]] * [1, 0]^T = [1, 2]
    VERIFY_IS_APPROX(result, Vector2(1, 2));

    v = Vector2(0, 1);
    result = t.linear() * v;
    // [[1, 3], [2, 1]] * [0, 1]^T = [3, 1]
    VERIFY_IS_APPROX(result, Vector2(3, 1));
  }
}

EIGEN_DECLARE_TEST(geo_misc) {
  for (int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1(angleaxis_edge_cases<float>());
    CALL_SUBTEST_2(angleaxis_edge_cases<double>());

    CALL_SUBTEST_3(rotation2d_standalone<float>());
    CALL_SUBTEST_4(rotation2d_standalone<double>());

    CALL_SUBTEST_5(translation_standalone<float>());
    CALL_SUBTEST_5(translation_standalone<double>());

    CALL_SUBTEST_6(scaling_standalone<float>());
    CALL_SUBTEST_6(scaling_standalone<double>());

    CALL_SUBTEST_7(quaternion_from_non_orthogonal_matrix<float>());
    CALL_SUBTEST_7(quaternion_from_non_orthogonal_matrix<double>());

    CALL_SUBTEST_8(quaternion_slerp_edge_cases<float>());
    CALL_SUBTEST_8(quaternion_slerp_edge_cases<double>());

    CALL_SUBTEST_9(umeyama_degenerate<float>());
    CALL_SUBTEST_9(umeyama_degenerate<double>());

    CALL_SUBTEST_10(shear_ground_truth<float>());
    CALL_SUBTEST_10(shear_ground_truth<double>());
  }
}
