Eigen is written and maintained by volunteers. Contributions — code, documentation, bug triage, tests on uncommon platforms, design feedback — are all welcome.
This document is the human-facing on-ramp. For the deeper “how this codebase actually works” reference (architecture, expression templates, SIMD layer, GPU stories, pitfalls), see AGENTS.md; it's written for AI coding agents but is also the most up-to-date single-file overview of the repo.
AGENTS.md and this file)You don't have to write C++ to help.
decision needed. Issues labelled contributions welcome are good entry points.libeigen/eigen as an upstream remote (use the https:// clone URL if you don't have an SSH key set up):git clone git@gitlab.com:<your-username>/eigen.git # or: https://gitlab.com/<your-username>/eigen.git cd eigen git remote add upstream https://gitlab.com/libeigen/eigen.git
master for your change:git fetch upstream git checkout -b my-topic upstream/master
clang-format-17 (see Coding standards).Area: short imperative subject message (see Commit messages). Stage files by path — don't use git add -A.libeigen/eigen master.If you're planning a large change (new module, API redesign, significant refactor), open an issue or start a discussion first. Aligning on direction before you write code avoids wasted work for everyone.
Eigen is header-only, so consumers don't need to build the library itself — but contributors do need to build the test suite. CMake configure happens out-of-source, and tests are intentionally not in the default all target — drive everything through the named targets.
cmake -S . -B build -G Ninja cmake --build build --target buildtests # build all unit tests cmake --build build --target check # build + run all tests cmake --build build --target buildsmoketests # the smoke set CI gates MRs on ctest --test-dir build --parallel --output-on-failure
Other useful targets: BuildOfficial (just test/), BuildUnsupported (just unsupported/test/), buildtests_gpu, check_gpu. Once configured, the build dir also exposes ./buildtests.sh <regex> and ./check.sh <regex> for narrowing by test-name regex.
Full reference for CMake options (per-ISA test flags, GPU/SYCL toggles, external BLAS/LAPACK, etc.), the test-split mechanism, and the VERIFY_* macro family lives in AGENTS.md § “Build / test”.
In-flight migration: MR 2159 is migrating the test framework from Eigen's own
EIGEN_DECLARE_TEST/CALL_SUBTEST_Nmacros to Google Test. Until it lands, write new tests with the existing framework (test/main.h,VERIFY_*,EIGEN_DECLARE_TEST,ei_add_testin the matchingCMakeLists.txt).In-flight rename: MR 2522 renames the top-level
unsupported/directory tocontrib/. Paths in this document follow master (stillunsupported/); substitutecontrib/mechanically once it lands.
benchmarks/ or unsupported/benchmarks/. Don't defer benchmarks to a follow-up MR.test/packetmath.cpp entry (or unsupported/test/special_packetmath.cpp for special functions), and a specialization in every architecture backend that supports the type. Eigen/src/Core/arch/Default/ holds generic SIMD implementations shared across backends; scalar fallbacks live in Eigen/src/Core/GenericPacketMath.h and Eigen/src/Core/MathFunctions.h.uptime shows a low load average, finish or cancel background builds, and never run two benchmark binaries in the same shell invocation (parallel or chained with &&). Run each in its own shell, take medians within a binary, and optionally alternate (A, B, A, B) across separate invocations to detect drift.Eigen has a few hard rules that catch contributors most often. The full discussion is in AGENTS.md § “Agent guidelines (read first)”; the short version:
#include anything under Eigen/src/... or unsupported/Eigen/src/... — InternalHeaderCheck.h makes that a hard compile error. User code reaches implementation only through the umbrella headers (Eigen/Core, Eigen/Dense, Eigen/SVD, …).EIGEN_DEVICE_FUNC on coefficient-level methods. Dropping it silently breaks CUDA / HIP / SYCL builds and rarely shows up in local testing.clang-format-17 exactly — Google base, 120 columns, configured in .clang-format. Newer or older clang-format will diff against CI. Run scripts/format.sh (whole tree) or clang-format-17 -i <file> (one file) before pushing. Format failures are the single most common reason an MR is red.modernize-* / cppcoreguidelines-* clang-tidy fixes, no replacing EIGEN_STRONG_INLINE with inline, no reordering includes (.clang-format has SortIncludes: false). Eigen's conventions are encoded in .clang-format‘s StatementMacros and AttributeMacros lists — don’t “fix” their indentation.test/main.h, not gtest (today — see migration note above). VERIFY_* assertions, CALL_SUBTEST_N / EIGEN_TEST_PART_N for splitting, EIGEN_DECLARE_TEST(<name>) { ... } as the entry point.auto traps. auto x = A + B; captures a lazy expression holding references that can dangle. Use .eval() or an explicit type. Similarly, .noalias() is a promise from the caller — only use it when the destination doesn't appear on the right side (so mat.noalias() = mat * mat is wrong).git add -A / git add . — the repo root accumulates .vscode/, .idea/, build*/, and other untracked files that must not enter commits. Add by path or with targeted globs.Naming conventions:
Matrix, BDCSVD).coeffRef, applyOnTheLeft).EIGEN_UPPER_CASE (EIGEN_DEVICE_FUNC, EIGEN_STRONG_INLINE).Eigen::internal namespace; public API stays in Eigen:: or module namespaces.eigen_assert(cond) for runtime preconditions (not raw assert); EIGEN_STATIC_ASSERT(cond, MSG_TOKEN) for compile-time conditions; eigen_internal_assert for internal-only invariants gated on EIGEN_INTERNAL_DEBUGGING.The canonical class layout is visible in recent additions such as unsupported/Eigen/src/GPU/DeviceMatrix.h. Template parameters that get re-exported as public aliases carry a trailing underscore (template <typename Scalar_, ...> paired with using Scalar = Scalar_; — prefer using over typedef in new code), member variables use an m_ prefix (m_matrix, m_isInitialized), implementation headers under Eigen/src/... begin with // IWYU pragma: private and #include "./InternalHeaderCheck.h", header guards follow EIGEN_<NAME>_H, and implementation detail lives inside nested namespace Eigen { namespace internal { ... } }. Public classes carry Doxygen blocks (\class, \brief, \tparam, \sa) and link to runnable snippets from doc/snippets/ via \include / \verbinclude. When in doubt, copy the style from a recent neighbouring file rather than inventing a new convention.
Every new source file must carry an inline copyright + license header. The checkformat:reuse CI job (reuse lint) blocks otherwise. Two header styles are in active use; pick whichever fits.
Attributed to an individual contributor:
// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) <year> <Your Name> <your.email@example.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
Attributed collectively (common for files written by multiple contributors, or where individual attribution isn't useful):
// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) <year> The Eigen Authors. // // 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
Markdown docs, generated files (*.in), and binary assets that can‘t carry inline headers are covered by path annotations in REUSE.toml — add your path there if you’re creating one.
This is non-negotiable.
\note block is enough.user.name and user.email in your git config are set to credit you correctly.The Eigen Authors attribution is fine when individual credit isn’t useful.Format: Area: short imperative subject.
Examples (from recent history):
BDCSVD: fix edge caseGPU: Drop direct LruCache.h include from CuBlasSupport.hci: drop CodeRabbit summaryTriangularView: alias-aware fallback for structured-diagonal product fast pathKeep the subject under ~72 characters; use the body for the why, not the what — the diff already shows what changed. Reference issues by #<n> when relevant.
Eigen aspires to state-of-the-art on two axes — performance and numerical accuracy / IEEE-754 conformance — and treats them as separate goals that are sometimes in tension.
EIGEN_GEMM_THREADPOOL) and covers a subset of operations. The Tensor module is multi-core by design via ThreadPoolDevice.log(0), pow(0, 0)) the bar is exact conformance to IEEE 754 / ISO C / C++ specifications, with cppreference as the authoritative spec. Special-value handling is not subject to the few-ULPs trade-off.For decompositions and solvers specifically, the bar is matching LAPACK on conditioning, pivoting strategy, and backward stability. Don't trade numerical robustness for speed in those code paths without explicit sign-off.
Some “unsupported” modules carry stability guarantees beyond what the name suggests:
unsupported/Eigen/Tensor and Eigen/ThreadPool together form TensorFlow's core compute backend. “Unsupported” here means looser API-stability guarantees — it does not mean low-traffic or low-stakes. Breaking changes to header layout, signatures, semantics, or contraction / reduction kernel performance ripple into every TensorFlow build. Prefer additive changes, keep header paths stable, run unsupported/test/tensor_* before submitting, and call out any behaviour change prominently in the MR description.AGENTS.md — deep dive on architecture, expression templates, evaluators, the SIMD packet layer, CUDA / HIP / SYCL, multi-threading, common pitfalls, and CI structure.README.md — high-level project description and pointers to the websites.CHANGELOG.md — release-by-release notes.Thank you for contributing to Eigen!