| // 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()); | |
| } |