// main.h adds instrumentation which breaks constexpr so we do not run any tests in here, // this is strictly compile-time. #include #include using namespace Eigen; template struct AssertConstexpr {}; #define assert_constexpr(expr) \ do { \ (void) AssertConstexpr<(expr, 1)>(); \ } while (false) constexpr bool zeroSized() { constexpr Matrix m0; static_assert(m0.size() == 0, ""); constexpr Matrix m1; static_assert(m0 == m1, ""); static_assert(!(m0 != m1), ""); constexpr Array a0; static_assert(a0.size() == 0, ""); constexpr Array a1; static_assert((a0 == a1).all(), ""); static_assert((a0 != a1).count() == 0, ""); constexpr Array 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 m(static_data); static_assert(m(0) == 1, ""); constexpr Map> 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 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 m(static_data); constexpr auto block = m.block<2,1>(0, 1); constexpr Map v(static_data + 2); static_assert(block == v, ""); return true; } static_assert(blocks(), ""); constexpr bool diagonal_row_columns() { constexpr Map 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> 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> m(static_data_antisym); static_assert(m.size() == 9, ""); return true; } static_assert(reductions(), ""); constexpr bool scalar_mult_div() { constexpr Map 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::Ones(2,3).size() == 6, ""); static_assert(Matrix::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::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 dynMap(static_data_antisym, 3, 3); constexpr Map 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> m(static_data); constexpr auto b(m.block<2,2>(0,0)); // 1 2 5 6 constexpr Map m2(static_data); // 1 2 3 4 static_assert((b + m2).col(0) == 2*Map(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(); }