| // main.h adds instrumentation which breaks constexpr so we do not run any tests in here, |
| // this is strictly compile-time. |
| #include <Eigen/Dense> |
| #include <Eigen/Geometry> |
| |
| using namespace Eigen; |
| |
| template<int Blah> |
| struct AssertConstexpr {}; |
| #define assert_constexpr(expr) \ |
| do { \ |
| (void) AssertConstexpr<(expr, 1)>(); \ |
| } while (false) |
| |
| constexpr bool zeroSized() |
| { |
| constexpr Matrix<float, 0, 0> m0; |
| static_assert(m0.size() == 0, ""); |
| |
| constexpr Matrix<float, 0, 0> m1; |
| static_assert(m0 == m1, ""); |
| static_assert(!(m0 != m1), ""); |
| |
| constexpr Array<int, 0, 0> a0; |
| static_assert(a0.size() == 0, ""); |
| |
| constexpr Array<int, 0, 0> a1; |
| static_assert((a0 == a1).all(), ""); |
| static_assert((a0 != a1).count() == 0, ""); |
| |
| constexpr Array<float, 0, 0> af; |
| static_assert(m0 == af.matrix(), ""); |
| static_assert((m0.array() == af).all(), ""); |
| static_assert(m0.array().matrix() == m0, ""); |
| |
| return true; |
| } |
| |
| static_assert(zeroSized(), ""); |
| |
| static constexpr double static_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; |
| |
| constexpr bool maps() |
| { |
| constexpr Map<const Vector4d> m(static_data); |
| static_assert(m(0) == 1, ""); |
| constexpr Map<const Array<double, 4, 1>> a(static_data); |
| static_assert(m == a.matrix(), ""); |
| static_assert(m.size() == 4, ""); |
| static_assert(a.size() == 4, ""); |
| static_assert(m.rows() == 4 && m.cols() == 1, ""); |
| return true; |
| } |
| |
| static_assert(maps(), ""); |
| |
| constexpr bool nc_maps() |
| { |
| bool result = true; |
| |
| double d[] = {1, 2, 3, 4}; |
| Map<Vector4d> m(d); |
| result = result && (m.x() == 1 && m.y() == 2 && m.z() == 3 && m.w() == 4); |
| |
| float array[3] = {}; |
| auto v = Vector3f::Map(array); |
| v.fill(10); |
| result = result && (v.array() == 10).all(); |
| |
| return result; |
| } |
| |
| constexpr bool blocks() |
| { |
| constexpr Map<const Matrix2d> m(static_data); |
| constexpr auto block = m.block<2,1>(0, 1); |
| |
| constexpr Map<const Vector2d> v(static_data + 2); |
| static_assert(block == v, ""); |
| |
| return true; |
| } |
| |
| static_assert(blocks(), ""); |
| |
| constexpr bool diagonal_row_columns() |
| { |
| constexpr Map<const Matrix2d> m(static_data); |
| static_assert(m.block<2,1>(0, 1) == m.col(1), ""); |
| static_assert(m.block<1,2>(1, 0) == m.row(1), ""); |
| static_assert(m.diagonal()(0) == 1 && m.diagonal()(1) == 4, ""); |
| return true; |
| } |
| |
| static_assert(diagonal_row_columns(), ""); |
| |
| static constexpr int static_data_antisym[] = { |
| 0, 1, -1, |
| -1, 0, 1, |
| 1, -1, 0 }; |
| |
| constexpr bool transpose_unaryminus() |
| { |
| constexpr Map<const Matrix<int, 3, 3>> m(static_data_antisym); |
| |
| static_assert(m.transpose() == -m, ""); |
| static_assert(-m.transpose() == m, ""); |
| static_assert((-m).transpose() == m, ""); |
| |
| static_assert(m.transpose() != m, ""); |
| static_assert(-m.transpose() != -m, ""); |
| static_assert((-m).transpose() != -m, ""); |
| |
| return true; |
| } |
| |
| static_assert(transpose_unaryminus(), ""); |
| |
| constexpr bool reductions() |
| { |
| constexpr Map<const Matrix<int, 3, 3>> m(static_data_antisym); |
| static_assert(m.size() == 9, ""); |
| |
| return true; |
| } |
| |
| static_assert(reductions(), ""); |
| |
| constexpr bool scalar_mult_div() |
| { |
| constexpr Map<const Matrix2d> m(static_data); |
| |
| static_assert((m * 2)(0,0) == 2, ""); |
| static_assert((m / 2)(1,1) == 2*m(0,0), ""); |
| |
| constexpr double c = 8; |
| static_assert((m * c)(0,0) == 8, ""); |
| static_assert((m.array() / c).matrix() == 1/c * m, ""); |
| return true; |
| } |
| |
| static_assert(scalar_mult_div(), ""); |
| |
| constexpr bool constant_identity() |
| { |
| static_assert(Matrix3f::Zero()(0,0) == 0, ""); |
| static_assert(Matrix4d::Ones()(3,3) == 1, ""); |
| static_assert(Matrix2i::Identity()(0,0) == 1 && Matrix2i::Identity()(1,0) == 0, ""); |
| static_assert(Matrix<float, Dynamic, Dynamic>::Ones(2,3).size() == 6, ""); |
| static_assert(Matrix<float, Dynamic, 1>::Zero(10).rows() == 10, ""); |
| |
| return true; |
| } |
| |
| static_assert(constant_identity(), ""); |
| |
| constexpr bool dynamic_basics() |
| { |
| // This verifies that we only calculate the entry that we need. |
| static_assert(Matrix<double, Dynamic, Dynamic>::Identity(50000,50000).array()(25,25) == 1, ""); |
| |
| static_assert(Matrix4d::Identity().block(1,1,2,2)(0,1) == 0, ""); |
| static_assert(MatrixXf::Identity(50,50).transpose() == MatrixXf::Identity(50, 50), ""); |
| |
| constexpr Map<const MatrixXi> dynMap(static_data_antisym, 3, 3); |
| constexpr Map<const Matrix3i> staticMap(static_data_antisym); |
| static_assert(dynMap == staticMap, ""); |
| static_assert(dynMap.transpose() != staticMap, ""); |
| // e.g. this hits an assertion at compile-time that would otherwise fail at runtime. |
| //static_assert(dynMap != staticMap.block(1,2,0,0)); |
| |
| return true; |
| } |
| |
| static_assert(dynamic_basics(), ""); |
| |
| constexpr bool sums() |
| { |
| constexpr Map<const Matrix<double, 4, 4>> m(static_data); |
| constexpr auto b(m.block<2,2>(0,0)); // 1 2 5 6 |
| constexpr Map<const Matrix2d> m2(static_data); // 1 2 3 4 |
| |
| static_assert((b + m2).col(0) == 2*Map<const Vector2d>(static_data), ""); |
| static_assert(b + m2 == m2 + b, ""); |
| |
| static_assert((b - m2).col(0) == Vector2d::Zero(), ""); |
| static_assert((b - m2).col(1) == 2*Vector2d::Ones(), ""); |
| |
| static_assert((2*b - m2).col(0) == b.col(0), ""); |
| static_assert((b - 2*m2).col(0) == -b.col(0), ""); |
| |
| static_assert((b - m2 + b + m2 - 2*b) == Matrix2d::Zero(), ""); |
| |
| return true; |
| } |
| |
| static_assert(sums(), ""); |
| |
| constexpr bool unit_vectors() |
| { |
| static_assert(Vector4d::UnitX()(0) == 1, ""); |
| static_assert(Vector4d::UnitY()(1) == 1, ""); |
| static_assert(Vector4d::UnitZ()(2) == 1, ""); |
| static_assert(Vector4d::UnitW()(3) == 1, ""); |
| |
| static_assert(Vector4d::UnitX().dot(Vector4d::UnitX()) == 1, ""); |
| static_assert(Vector4d::UnitX().dot(Vector4d::UnitY()) == 0, ""); |
| static_assert((Vector4d::UnitX() + Vector4d::UnitZ()).dot(Vector4d::UnitY() + Vector4d::UnitW()) == 0, ""); |
| |
| return true; |
| } |
| |
| static_assert(unit_vectors(), ""); |
| |
| constexpr bool construct_from_other() |
| { |
| return true; |
| } |
| |
| static_assert(construct_from_other(), ""); |
| |
| constexpr bool construct_from_values() |
| { |
| return true; |
| } |
| |
| static_assert(construct_from_values(), ""); |
| |
| constexpr bool triangular() |
| { |
| bool result = true; |
| |
| return result; |
| } |
| |
| static_assert(triangular(), ""); |
| |
| constexpr bool nc_construct_from_values() |
| { |
| bool result = true; |
| |
| return result; |
| } |
| |
| constexpr bool nc_crossproduct() |
| { |
| bool result = true; |
| return result; |
| } |
| |
| constexpr bool nc_cast() |
| { |
| bool result = true; |
| |
| return result; |
| } |
| |
| constexpr bool nc_product() |
| { |
| bool result = true; |
| return result; |
| } |
| |
| static constexpr double static_data_quat[] = { 0, 1, 1, 0 }; |
| |
| constexpr bool nc_quat_mult() |
| { |
| bool result = static_data_quat[3] == 0; // Silence warning about unused with C++14 |
| |
| return result; |
| } |
| |
| // Run tests that aren't explicitly constexpr. |
| constexpr bool test_nc() |
| { |
| assert_constexpr(nc_maps()); |
| assert_constexpr(nc_construct_from_values()); |
| assert_constexpr(nc_crossproduct()); |
| assert_constexpr(nc_cast()); |
| assert_constexpr(nc_product()); |
| assert_constexpr(nc_quat_mult()); |
| return true; |
| } |
| |
| int main() |
| { |
| return !test_nc(); |
| } |