blob: ca1eff96e9b4c5602790e3bc395ac9a88a34f18f [file]
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// 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-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
// Checks that the configuration macros documented in
// doc/TopicPreprocessorDirectives.dox are still honored by the declarations
// that spell them.
//
// A mechanical rewrite of such a declaration prints the *resolved* type, so
// `typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;` silently becomes
// `using Index = std::ptrdiff_t;`. Every default-configured build stays green;
// only a translation unit that overrides the macro notices. Each part below
// therefore compiles with a different configuration.
#if defined(EIGEN_TEST_PART_2)
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#elif defined(EIGEN_TEST_PART_3)
#define EIGEN_64BIT_BLAS
#elif defined(EIGEN_TEST_PART_4)
#define EIGEN_ALIGN_TO_AVOID_FALSE_SHARING EIGEN_ALIGN_TO_BOUNDARY(256)
#elif defined(EIGEN_TEST_PART_5)
#define EIGEN_INITIALIZE_MATRICES_BY_NAN
#endif
#include "main.h"
// The index type must follow EIGEN_DEFAULT_DENSE_INDEX_TYPE in every configuration.
static_assert(std::is_same<Eigen::Index, EIGEN_DEFAULT_DENSE_INDEX_TYPE>::value,
"Eigen::Index no longer follows EIGEN_DEFAULT_DENSE_INDEX_TYPE");
static_assert(std::is_same<Eigen::DenseIndex, EIGEN_DEFAULT_DENSE_INDEX_TYPE>::value,
"Eigen::DenseIndex no longer follows EIGEN_DEFAULT_DENSE_INDEX_TYPE");
// Outside of MKL, the BLAS integer type must follow EIGEN_BLAS_INT, which the
// external BLAS prototypes in Eigen/src/Core/util/blas.h are declared with.
#if !defined(EIGEN_USE_MKL)
static_assert(std::is_same<Eigen::BlasIndex, EIGEN_BLAS_INT>::value,
"Eigen::BlasIndex no longer follows EIGEN_BLAS_INT");
#endif
// Buffers that Eigen aligns itself must be mapped with EIGEN_DEFAULT_ALIGN_BYTES,
// not with whatever that happened to expand to on the machine of the last edit.
static_assert(int(Eigen::internal::traits<
Eigen::internal::local_nested_eval_wrapper<Eigen::MatrixXd, 2, true>::ObjectType>::Alignment) ==
EIGEN_DEFAULT_ALIGN_BYTES,
"local_nested_eval_wrapper no longer follows EIGEN_DEFAULT_ALIGN_BYTES");
// EIGEN_ALIGN_TO_AVOID_FALSE_SHARING must honor pre-existing definitions and stay pinned to 128 by default.
struct AvoidFalseSharingAligned {
EIGEN_ALIGN_TO_AVOID_FALSE_SHARING char c;
};
#if defined(EIGEN_TEST_PART_4)
static_assert(alignof(AvoidFalseSharingAligned) == 256,
"Pre-existing EIGEN_ALIGN_TO_AVOID_FALSE_SHARING definition was not preserved");
#else
static_assert(alignof(AvoidFalseSharingAligned) == 128,
"EIGEN_ALIGN_TO_AVOID_FALSE_SHARING should be pinned to 128 bytes by default");
#endif
// Per-part checks that the override actually took effect.
#if defined(EIGEN_TEST_PART_2)
static_assert(std::is_same<Eigen::Index, int>::value, "EIGEN_DEFAULT_DENSE_INDEX_TYPE was ignored");
#endif
#if defined(EIGEN_TEST_PART_3) && !defined(EIGEN_USE_MKL)
static_assert(sizeof(Eigen::BlasIndex) == 8, "EIGEN_64BIT_BLAS was ignored");
#endif
void check_index_type() {
VERIFY_IS_EQUAL(int(sizeof(Eigen::Index)), int(sizeof(EIGEN_DEFAULT_DENSE_INDEX_TYPE)));
// The configured index type is the one the containers actually index with.
MatrixXd m(3, 4);
VERIFY_IS_EQUAL(m.rows(), Eigen::Index(3));
VERIFY_IS_EQUAL(m.cols(), Eigen::Index(4));
}
void check_blas_index() {
#if !defined(EIGEN_USE_MKL)
VERIFY_IS_EQUAL(int(sizeof(Eigen::BlasIndex)), int(sizeof(EIGEN_BLAS_INT)));
#endif
}
void check_false_sharing_alignment() {
#if defined(EIGEN_TEST_PART_4)
VERIFY_IS_EQUAL(std::size_t(alignof(AvoidFalseSharingAligned)), std::size_t(256));
#else
VERIFY_IS_EQUAL(std::size_t(alignof(AvoidFalseSharingAligned)), std::size_t(128));
#endif
}
// EIGEN_INITIALIZE_MATRICES_BY_NAN initializes new entries after resizing, including those that conservativeResize
// appends, whether it reallocates the storage in place (same leading dimension) or copies it.
void check_initialize_by_nan() {
#if defined(EIGEN_TEST_PART_5)
MatrixXd m(2, 3);
VERIFY(m.array().isNaN().all());
m.setZero(2, 2);
m.conservativeResize(2, 3);
VERIFY(m.leftCols(2).isZero(0) && m.col(2).array().isNaN().all());
m.conservativeResize(3, 3);
VERIFY(m.row(2).array().isNaN().all());
Matrix<double, Dynamic, Dynamic, RowMajor> r = Matrix<double, Dynamic, Dynamic, RowMajor>::Zero(2, 2);
r.conservativeResize(3, 2);
VERIFY(r.topRows(2).isZero(0) && r.row(2).array().isNaN().all());
VectorXd v = VectorXd::Zero(2);
v.conservativeResize(5);
VERIFY(v.head(2).isZero(0) && v.tail(3).array().isNaN().all());
Matrix<double, Dynamic, Dynamic, ColMajor, 4, 4> f = Matrix<double, Dynamic, Dynamic, ColMajor, 4, 4>::Zero(2, 2);
f.conservativeResize(2, 4);
VERIFY(f.leftCols(2).isZero(0) && f.rightCols(2).array().isNaN().all());
// Shrinking appends nothing and conservativeResizeLike() assigns what it appends, so both reallocate in place.
m.setOnes(3, 3);
m.conservativeResize(3, 2);
VERIFY_IS_EQUAL(m, MatrixXd::Ones(3, 2));
r.setOnes(3, 2);
r.conservativeResize(1, 2);
VERIFY_IS_EQUAL(r, (Matrix<double, Dynamic, Dynamic, RowMajor>::Ones(1, 2)));
v.setOnes(5);
v.conservativeResize(3);
VERIFY_IS_EQUAL(v, VectorXd::Ones(3));
m.conservativeResizeLike(MatrixXd::Constant(3, 4, 2));
VERIFY(m.leftCols(2).isOnes(0) && (m.rightCols(2).array() == 2).all());
v.conservativeResizeLike(VectorXd::Constant(5, 2));
VERIFY(v.head(3).isOnes(0) && (v.tail(2).array() == 2).all());
#endif
}
EIGEN_DECLARE_TEST(preprocessor_directives) {
CALL_SUBTEST_1(check_index_type());
CALL_SUBTEST_1(check_false_sharing_alignment());
CALL_SUBTEST_2(check_index_type());
CALL_SUBTEST_3(check_blas_index());
CALL_SUBTEST_4(check_false_sharing_alignment());
CALL_SUBTEST_5(check_initialize_by_nan());
}