Refactor: rename top-level unsupported/ to contrib/

libeigen/eigen!2522

Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
diff --git a/.agents/benchmarking.md b/.agents/benchmarking.md
index c9ac01f..1f62f60 100644
--- a/.agents/benchmarking.md
+++ b/.agents/benchmarking.md
@@ -5,26 +5,26 @@
 
 ## Projects and Builds
 
-The supported and unsupported benchmark trees are separate, standalone CMake projects. They are not part of Eigen's
+The supported and contrib benchmark trees are separate, standalone CMake projects. They are not part of Eigen's
 main test build and both require Google Benchmark:
 
 ```bash
 cmake -G Ninja -S benchmarks -B build-bench -DCMAKE_BUILD_TYPE=Release
 cmake --build build-bench --target <benchmark-target>
 
-cmake -G Ninja -S unsupported/benchmarks -B build-unsupported-bench -DCMAKE_BUILD_TYPE=Release
-cmake --build build-unsupported-bench --target <benchmark-target>
+cmake -G Ninja -S contrib/benchmarks -B build-contrib-bench -DCMAKE_BUILD_TYPE=Release
+cmake --build build-contrib-bench --target <benchmark-target>
 ```
 
-The unsupported parent project automatically adds its GPU subtree when it detects `CUDAToolkit`. That configuration
+The contrib parent project automatically adds its GPU subtree when it detects `CUDAToolkit`. That configuration
 also requires a working CUDA compiler and architecture selection. On a host with only a partial toolkit installation,
-configure CPU-only unsupported benchmarks with `-DCMAKE_DISABLE_FIND_PACKAGE_CUDAToolkit=TRUE` or report the GPU
+configure CPU-only contrib benchmarks with `-DCMAKE_DISABLE_FIND_PACKAGE_CUDAToolkit=TRUE` or report the GPU
 configuration as unavailable.
 
 Consult [`benchmarks/CMakeLists.txt`](../benchmarks/CMakeLists.txt) and
-[`unsupported/benchmarks/CMakeLists.txt`](../unsupported/benchmarks/CMakeLists.txt) for current targets and compile
+[`contrib/benchmarks/CMakeLists.txt`](../contrib/benchmarks/CMakeLists.txt) for current targets and compile
 settings. CUDA benchmarks also have a standalone project and instructions in
-[`unsupported/benchmarks/GPU/CMakeLists.txt`](../unsupported/benchmarks/GPU/CMakeLists.txt). No CI job builds or runs
+[`contrib/benchmarks/GPU/CMakeLists.txt`](../contrib/benchmarks/GPU/CMakeLists.txt). No CI job builds or runs
 benchmarks, so the pipeline validates neither a benchmark's own compilation nor a performance claim: build and run
 both locally, and report the measurement conditions this guide requires.
 
diff --git a/.agents/ci.md b/.agents/ci.md
index 90d120e..df34224 100644
--- a/.agents/ci.md
+++ b/.agents/ci.md
@@ -214,7 +214,7 @@
 `.clang-tidy` policy is authoritative. Do not apply generic `modernize-*` or `cppcoreguidelines-*` campaigns.
 
 A module that reaches a third-party header the machine does not install — `<cuda_runtime.h>` from
-`unsupported/Eigen/src/GPU`, `<cholmod.h>` from `CholmodSupport` — is still checked, but clang parses a truncated
+`contrib/Eigen/src/GPU`, `<cholmod.h>` from `CholmodSupport` — is still checked, but clang parses a truncated
 translation unit, so the driver marks the heading `— partial: <header> is not installed` and reports that file's
 findings without failing the job. Installing the dependency gets the module checked in full; for CUDA the driver
 looks under `CUDAToolkit_ROOT`, `CUDA_HOME`, `CUDA_PATH`, then `/usr/local/cuda`, and so does
diff --git a/.agents/conventions.md b/.agents/conventions.md
index 2fae415..26489c7 100644
--- a/.agents/conventions.md
+++ b/.agents/conventions.md
@@ -14,7 +14,7 @@
   `template <...> constexpr T Cls<...>::kName;` definition exists (`arch/Default/Half.h` has the form). Pass a prvalue
   (`+kName`, `Index(kName)`) or add the definition; the test suite builds optimized and will not catch the omission.
 - Prefer `using` to `typedef`, `nullptr` to `NULL`, `= default` and default member initializers to empty constructor
-  bodies that assign each member. `using` binds in every tree, `test/` and `unsupported/` included: those were left
+  bodies that assign each member. `using` binds in every tree, `test/` and `contrib/` included: those were left
   out of the sweep that converted `Eigen/src`, so the aliases surrounding new code there are mostly still `typedef`
   and matching the neighbours reproduces the form the sweep removed. Do not rely on CI to catch it — the
   `modernize-use-using` gap recorded at [`scripts/check_style.py`](../scripts/check_style.py) leaves function-local
diff --git a/.agents/docs.md b/.agents/docs.md
index 683d894..0a5df41 100644
--- a/.agents/docs.md
+++ b/.agents/docs.md
@@ -2,7 +2,7 @@
 
 Use this guide when editing a Doxygen block, a page under [`doc/`](../doc), a snippet or example, or a documented public
 name. The documentation is the Doxygen comments in the headers, the topic pages in `doc/*.dox`, and the programs under
-[`doc/snippets`](../doc/snippets), [`doc/examples`](../doc/examples) and their `unsupported/doc` counterparts, which the
+[`doc/snippets`](../doc/snippets), [`doc/examples`](../doc/examples) and their `contrib/doc` counterparts, which the
 `doc` target compiles and runs to produce the output the pages embed. Keep the Doxygen block above a changed
 declaration describing the current behavior, preconditions, and return value, and give a module `README` that names a
 moved value the same update.
@@ -25,8 +25,8 @@
 The `doc` target also compiles and runs the configured examples and snippets, by way of the `all_snippets` and
 `all_examples` prerequisites in [`doc/CMakeLists.txt`](../doc/CMakeLists.txt). A renamed or removed public name breaks
 the documentation build even when every comment is well formed, so search those directories before changing one.
-"Configured" is the operative word: `unsupported/doc/examples/CMakeLists.txt` adds its `SYCL` subdirectory only under
-`EIGEN_TEST_SYCL`, which `build:linux:docs` does not set, so a broken unsupported SYCL example leaves this target green.
+"Configured" is the operative word: `contrib/doc/examples/CMakeLists.txt` adds its `SYCL` subdirectory only under
+`EIGEN_TEST_SYCL`, which `build:linux:docs` does not set, so a broken contrib SYCL example leaves this target green.
 Treat the target as coverage for the sets the configuration actually enables, and check the conditional before citing
 it as coverage.
 
diff --git a/.agents/numerics.md b/.agents/numerics.md
index 673d128..244b548 100644
--- a/.agents/numerics.md
+++ b/.agents/numerics.md
@@ -81,7 +81,7 @@
 
 - Test the scalar path, generic packet fallback, and every affected backend specialization that is available. Build
   and run [`test/packetmath.cpp`](../test/packetmath.cpp) and, for special functions,
-  [`unsupported/test/special_packetmath.cpp`](../unsupported/test/special_packetmath.cpp). Report backends that were
+  [`contrib/test/special_packetmath.cpp`](../contrib/test/special_packetmath.cpp). Report backends that were
   not available locally.
 - Compare packet results with the scalar contract for special values, but use MPFR rather than assuming the scalar
   standard-library result is accurate enough to set a new finite-input ULP target.
diff --git a/.agents/simd-gpu.md b/.agents/simd-gpu.md
index fd32f5d..51599a6 100644
--- a/.agents/simd-gpu.md
+++ b/.agents/simd-gpu.md
@@ -1,7 +1,7 @@
 # SIMD and GPU Changes
 
 Use this guide for packet math, architecture backends, device annotations, CUDA/HIP/SYCL code, Tensor device
-execution, and the `unsupported/Eigen/GPU` module. The repository-root `AGENTS.md` still applies.
+execution, and the `contrib/Eigen/GPU` module. The repository-root `AGENTS.md` still applies.
 
 ## Packet math
 
@@ -48,7 +48,7 @@
 - Define configuration macros before the first Eigen public header and keep index configuration consistent across
   translation units that exchange Eigen objects.
 - Include public module headers in tests and examples. Implementation headers under `Eigen/src/` and
-  `unsupported/Eigen/src/` are not user include points.
+  `contrib/Eigen/src/` are not user include points.
 
 ## Three GPU models
 
@@ -66,18 +66,18 @@
 
 ### Tensor devices
 
-`unsupported/Eigen/Tensor` evaluates expressions through an explicit device. `GpuDevice` handles CUDA/HIP and
+`contrib/Eigen/Tensor` evaluates expressions through an explicit device. `GpuDevice` handles CUDA/HIP and
 `SyclDevice` handles SYCL; Tensor GPU kernels remain part of the Tensor implementation. Device-resident storage is
 normally supplied through `TensorMap`, and the destination selects execution with `out.device(device) = expression`.
-Consult `unsupported/Eigen/src/Tensor/README.md` and the nearby device implementation before changing memory,
+Consult `contrib/Eigen/src/Tensor/README.md` and the nearby device implementation before changing memory,
 synchronization, or callback semantics.
 
-### `unsupported/Eigen/GPU`
+### `contrib/Eigen/GPU`
 
 This is a host-side NVIDIA-library wrapper selected explicitly with `Eigen::gpu` types. `gpu::DeviceMatrix` is not a
 `MatrixBase` expression, and a supported expression maps to a CUDA library operation rather than Core coefficient
-evaluation or packet fusion. Define `EIGEN_USE_GPU` before including `<unsupported/Eigen/GPU>`, and consult
-`unsupported/Eigen/src/GPU/README.md`. Its tests under `unsupported/test/GPU/` are intentionally host-compiled `.cpp`
+evaluation or packet fusion. Define `EIGEN_USE_GPU` before including `<contrib/Eigen/GPU>`, and consult
+`contrib/Eigen/src/GPU/README.md`. Its tests under `contrib/test/GPU/` are intentionally host-compiled `.cpp`
 files.
 
 Asynchrony makes otherwise-ordinary refactors unsafe in this module. Freeing, reusing, or destroying memory, streams,
@@ -94,7 +94,7 @@
 - Core device-callability changes: build and run the relevant `gpu_basic` or `gpu_example` target with the available
   CUDA/HIP compiler.
 - Tensor device changes: run the operation's CPU Tensor test plus the matching CUDA/HIP/SYCL test where available.
-- `unsupported/Eigen/GPU` changes: run the focused target under `unsupported/test/GPU/` and any affected library
+- `contrib/Eigen/GPU` changes: run the focused target under `contrib/test/GPU/` and any affected library
   integration target enabled by the local toolkit.
 - Report backends or hardware that were unavailable. Do not claim cross-backend validation from a host-only build.
 
diff --git a/.agents/tensor-threadpool.md b/.agents/tensor-threadpool.md
index 01d3a62..bb90f54 100644
--- a/.agents/tensor-threadpool.md
+++ b/.agents/tensor-threadpool.md
@@ -1,18 +1,18 @@
 # Tensor and Thread-Pool Changes
 
-Use this guide for `unsupported/Eigen/Tensor`, `Eigen/ThreadPool`, Core's custom GEMM thread-pool backend, and explicit
+Use this guide for `contrib/Eigen/Tensor`, `Eigen/ThreadPool`, Core's custom GEMM thread-pool backend, and explicit
 thread-pool devices. The repository-root `AGENTS.md` still applies.
 
 ## Compatibility and risk
 
-Tensor and ThreadPool are foundational to TensorFlow and other downstream users. "Unsupported" describes Tensor's
-API-stability policy, not its importance. Changes to signatures, header layout, evaluation order, allocation,
+Tensor and ThreadPool are foundational to TensorFlow and other downstream users. The `contrib/` location describes
+Tensor's API-stability policy, not its importance. Changes to signatures, header layout, evaluation order, allocation,
 synchronization, numerical behavior, or performance can have a large downstream impact.
 
-- Prefer additive changes and preserve public header paths. Use `<unsupported/Eigen/Tensor>` and
+- Prefer additive changes and preserve public header paths. Use `<contrib/Eigen/Tensor>` and
   `<Eigen/ThreadPool>`; never expose implementation-header includes to users.
-- Paths below `unsupported/Eigen/CXX11/` are backward-compatibility forwarding shims only. New code must use the
-  canonical `unsupported/Eigen/` headers and must not add new headers under `CXX11/`.
+- Paths below `unsupported/Eigen/`, including `unsupported/Eigen/CXX11/`, are backward-compatibility forwarding
+  shims only. New code must use the canonical `contrib/Eigen/` headers and must not add headers under either.
 - Preserve `EIGEN_DEVICE_FUNC` on code reachable by CUDA, HIP, or SYCL device evaluation.
 - Treat evaluator flags, layouts, scalar/packet/block paths, zero-sized tensors, aliasing, and asynchronous object
   lifetimes as part of the behavior under test.
@@ -57,7 +57,7 @@
 
 ### Tensor `ThreadPoolDevice`
 
-Define `EIGEN_USE_THREADS` before `<unsupported/Eigen/Tensor>`, then construct a `ThreadPoolDevice` over an existing
+Define `EIGEN_USE_THREADS` before `<contrib/Eigen/Tensor>`, then construct a `ThreadPoolDevice` over an existing
 `ThreadPoolInterface` and evaluate explicitly:
 
 ```cpp
@@ -69,7 +69,7 @@
 The device does not own the pool. The pool, allocator, input storage, output storage, and callback state must remain
 alive until synchronous evaluation returns or asynchronous completion is signaled. Tensor's executor, contraction,
 reduction, and device code have `ThreadPoolDevice`-specific paths; a serial `DefaultDevice` test alone is insufficient.
-See `unsupported/Eigen/src/Tensor/README.md` and `TensorDeviceThreadPool.h`.
+See `contrib/Eigen/src/Tensor/README.md` and `TensorDeviceThreadPool.h`.
 
 ## Evaluator capability flags and cost
 
@@ -111,5 +111,5 @@
 - Tensor behavior shared with accelerators: also follow `simd-gpu.md` and run the locally available device tests.
 - Report unavailable sanitizers, GPU toolchains, platforms, and downstream TensorFlow validation explicitly.
 
-Use `test/CMakeLists.txt`, `unsupported/test/CMakeLists.txt`, and the checked-out CMake configuration as the source of
+Use `test/CMakeLists.txt`, `contrib/test/CMakeLists.txt`, and the checked-out CMake configuration as the source of
 truth for target names. Do not maintain a duplicate test or backend inventory here.
diff --git a/.agents/testing.md b/.agents/testing.md
index 11c6efa..0f3cbee 100644
--- a/.agents/testing.md
+++ b/.agents/testing.md
@@ -10,7 +10,7 @@
   [`test/type_test_helpers.h`](../test/type_test_helpers.h) define random-matrix and type utilities.
 - [`cmake/EigenTesting.cmake`](../cmake/EigenTesting.cmake) defines test registration and splitting.
 - [`test/CMakeLists.txt`](../test/CMakeLists.txt) and
-  [`unsupported/test/CMakeLists.txt`](../unsupported/test/CMakeLists.txt) register the suites.
+  [`contrib/test/CMakeLists.txt`](../contrib/test/CMakeLists.txt) register the suites.
 - [`cmake/EigenConfigureTesting.cmake`](../cmake/EigenConfigureTesting.cmake) defines aggregate build and check
   targets.
 
@@ -25,7 +25,7 @@
 ctest --test-dir build --parallel --output-on-failure --no-tests=error
 ```
 
-Useful aggregate targets are `BuildOfficial`, `BuildUnsupported`, `buildsmoketests`, `buildtests_gpu`, `check`, and
+Useful aggregate targets are `BuildOfficial`, `BuildContrib`, `buildsmoketests`, `buildtests_gpu`, `check`, and
 `check_gpu`. Build and run one test explicitly when possible:
 
 ```bash
@@ -60,7 +60,7 @@
 
 Eigen currently uses its own framework, not GoogleTest:
 
-1. Add `test/<name>.cpp` or `unsupported/test/<name>.cpp`.
+1. Add `test/<name>.cpp` or `contrib/test/<name>.cpp`.
 2. Include `main.h`, then the public umbrella header for tests of public behavior. A focused test of a private utility
    may include its implementation header only when that matches an established nearby pattern; never present such a
    path as a user include.
@@ -179,7 +179,7 @@
 
 Write such a bound as `factor * NumTraits<RealScalar>::epsilon()` at the site, and explain `factor` by its error
 model. Do not introduce tolerance wrapper helpers: the raw form is the established idiom across `test/` and
-`unsupported/test/`, and it *is* the computation, so a bound like `10 * n * eps * A.norm()` stays readable as one.
+`contrib/test/`, and it *is* the computation, so a bound like `10 * n * eps * A.norm()` stays readable as one.
 A bare decimal literal is worse than opaque — `1e-9` demands impossible accuracy from a `float` instantiation.
 
 Two ways a comparison silently accepts everything, both of which have shipped here: a tolerance computed by the
diff --git a/.clang-tidy b/.clang-tidy
index 00b829a..fdafd79 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -36,7 +36,7 @@
 
 WarningsAsErrors: ''
 
-HeaderFilterRegex: 'Eigen/.*|test/.*|blas/.*|lapack/.*|unsupported/Eigen/.*'
+HeaderFilterRegex: 'Eigen/.*|test/.*|blas/.*|lapack/.*|contrib/Eigen/.*'
 
 # Eigen uses its own assert macros.
 CheckOptions:
diff --git a/.coderabbit.yaml b/.coderabbit.yaml
index 2915ded..0bc1188 100644
--- a/.coderabbit.yaml
+++ b/.coderabbit.yaml
@@ -132,14 +132,14 @@
           verification over a Python reference. If such tests are missing,
           request them.
         - **Performance-sensitive changes ship with a benchmark** under
-          `benchmarks/` or `unsupported/benchmarks/`. Don't defer to a
+          `benchmarks/` or `contrib/benchmarks/`. Don't defer to a
           follow-up MR.
         - **Preserve `EIGEN_DEVICE_FUNC`.** It is pervasive on coefficient-
           level methods so the same code compiles for host and CUDA / HIP /
           SYCL device. Dropping it silently breaks GPU builds and is rarely
           caught locally — flag any removal or omission on new methods.
         - **Header-only contract.** Never include from `Eigen/src/...` (or
-          `unsupported/Eigen/src/...`) directly; reach implementation via
+          `contrib/Eigen/src/...`) directly; reach implementation via
           the umbrella module headers (`Eigen/Core`, `Eigen/Dense`, …).
           `InternalHeaderCheck.h` makes direct internal includes a hard
           error. Old internal headers do not get backward-compatibility
@@ -190,7 +190,7 @@
           across **every** backend that supports the type, with
           `arch/Default/` providing scalar fallbacks. A missing or divergent
           backend specialization usually shows up first in
-          `test/packetmath.cpp` or `unsupported/test/special_packetmath.cpp`
+          `test/packetmath.cpp` or `contrib/test/special_packetmath.cpp`
           — flag PRs that add a packet op in one backend without the others.
     - path: "{Eigen/ThreadPool,Eigen/src/ThreadPool/**}"
       instructions: |
@@ -219,12 +219,12 @@
         `TEST` / `TYPED_TEST` while bridging `VERIFY_*` to gtest
         expectations; once it lands, the "do not switch to gtest" rule
         flips for new tests.
-    - path: "unsupported/Eigen/**"
+    - path: "contrib/Eigen/**"
       instructions: |
-        "Unsupported" here means looser API-stability guarantees, **not**
+        The `contrib/` tree means looser API-stability guarantees, **not**
         low-traffic or low-stakes. The Tensor module
-        (`unsupported/Eigen/Tensor`, sources under
-        `unsupported/Eigen/src/Tensor/`) is TensorFlow's core compute
+        (`contrib/Eigen/Tensor`, sources under
+        `contrib/Eigen/src/Tensor/`) is TensorFlow's core compute
         backend; treat its signatures, header layout, semantics, and
         performance on contraction / reduction / morphing kernels as
         load-bearing. Prefer additive changes, keep header paths stable,
@@ -235,7 +235,7 @@
         preserve their public API. `unsupported/Eigen/CXX11/` is backward-
         compatibility forwarding shims only — do not place new headers
         there.
-    - path: "unsupported/Eigen/src/GPU/**"
+    - path: "contrib/Eigen/src/GPU/**"
       instructions: |
         Host-side dispatch to NVIDIA libraries (cuBLAS / cuSOLVER / cuFFT /
         cuSPARSE / cuDSS) on device-resident operands (`gpu::DeviceMatrix`).
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 58ad27e..db68150 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -69,7 +69,7 @@
   # If a test regex is specified, that will be selected.
   # Otherwise, we will try a label if specified.
   EIGEN_CI_CTEST_REGEX: ""
-  # Valid CTest labels: Official, Unsupported, gpu, smoketest.
+  # Valid CTest labels: Official, Contrib, gpu, smoketest.
   EIGEN_CI_CTEST_LABEL: ""
   EIGEN_CI_CTEST_ARGS: ""
   # Affected-test tier: paths to the selection written by the select:tests job.
diff --git a/AGENTS.md b/AGENTS.md
index 5c62fc5..6cd64ef 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -21,7 +21,7 @@
 | Numerical kernels, decompositions, solvers, accuracy | [`.agents/numerics.md`](.agents/numerics.md) |
 | Sparse matrices, sparse solvers, external sparse backends | [`.agents/sparse.md`](.agents/sparse.md) |
 | Performance changes and benchmarks | [`.agents/benchmarking.md`](.agents/benchmarking.md) |
-| Packet math, CUDA, HIP, SYCL, `unsupported/Eigen/GPU` | [`.agents/simd-gpu.md`](.agents/simd-gpu.md) |
+| Packet math, CUDA, HIP, SYCL, `contrib/Eigen/GPU` | [`.agents/simd-gpu.md`](.agents/simd-gpu.md) |
 | Tensor, ThreadPool, and multithreading | [`.agents/tensor-threadpool.md`](.agents/tensor-threadpool.md) |
 | Formatting, lint, and GitLab CI | [`.agents/ci.md`](.agents/ci.md) |
 | Doxygen blocks, `doc/` pages, snippets, and examples | [`.agents/docs.md`](.agents/docs.md) |
@@ -43,7 +43,7 @@
    actually produced the change is accurate attribution, not an invented one, and is permitted.
 3. **Respect the header-only and C++14 contracts.** Supported headers must compile as C++14 unless a guarded backend has
    a documented newer requirement. User code, examples, and public-behavior tests include umbrella headers such as
-   `Eigen/Core` or `Eigen/SVD`, not files below `Eigen/src/` or `unsupported/Eigen/src/`. Focused tests of private
+   `Eigen/Core` or `Eigen/SVD`, not files below `Eigen/src/` or `contrib/Eigen/src/`. Focused tests of private
    utilities may follow an established direct-include pattern, but those paths remain private even where a header is not
    mechanically guarded. Definitions in public headers must have valid header linkage and avoid ODR violations.
 4. **Protect compatibility.** Treat supported public names, signatures, header paths, semantics, and ABI-affecting
@@ -94,15 +94,16 @@
 ## Repository essentials
 
 Eigen is a header-only expression-template library. Consumers include module headers under `Eigen/` or
-`unsupported/Eigen/`. The top-level CMake project builds tests, documentation, demos, and BLAS/LAPACK shims rather than
+`contrib/Eigen/`. The top-level CMake project builds tests, documentation, demos, and BLAS/LAPACK shims rather than
 a core Eigen library; benchmarks use separate CMake projects. `Eigen/Dense` aggregates the dense modules, while
 `Eigen/Eigen` includes `Dense` and `Sparse`. External backend support modules and `Eigen/ThreadPool` remain separate
 includes. The upstream project is on GitLab; its GitHub repository is a read-only mirror.
 
 The supported implementation is under `Eigen/src/`; tests are under `test/`. Modules with looser API-stability
-guarantees are under `unsupported/Eigen/`, with tests under `unsupported/test/`. "Unsupported" does not imply low
-impact: Tensor is a foundational TensorFlow dependency. Public umbrella headers are the source of truth for a module's
-exported internals.
+guarantees are under `contrib/Eigen/`, with tests under `contrib/test/`. Legacy `unsupported/Eigen/...` include paths
+remain valid: one-line forwarding shims under `unsupported/Eigen/` point at the `contrib/` headers and are installed
+alongside them. "Contrib" does not imply low impact: Tensor is a foundational TensorFlow dependency. Public umbrella
+headers are the source of truth for a module's exported internals.
 
 The `lapack/*.f` files are vendored netlib LAPACK reference sources and are read-only here: do not edit them ad hoc,
 and flag a merge request that changes one unless it is an explicit refresh from a named netlib release, in which case
@@ -184,7 +185,7 @@
 For a split test such as `foo_3`, build that exact target and match it exactly with CTest, keeping `--no-tests=error`:
 a filter that matches nothing otherwise exits 0. The generated `buildtests.sh` and `check.sh` wrappers accept
 source/test-name regexes and are useful for building all matching parts.
-Use `buildtests`, `BuildOfficial`, `BuildUnsupported`, `buildsmoketests`, or `check` only when the requested validation
+Use `buildtests`, `BuildOfficial`, `BuildContrib`, `buildsmoketests`, or `check` only when the requested validation
 warrants that scope. See [`.agents/testing.md`](.agents/testing.md) for the current test framework, split rules,
 configuration variants, and failure-test workflow.
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5a40e4..b0fc470 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,13 @@
 Deprecations:
 - `ArrayBase::shiftRight<N>()` and `ArrayBase::shiftLeft<N>()`, in favour of `arithmeticShiftRight<N>()` and `logicalShiftLeft<N>()` [!2816]
 
+Other changes:
+- The top-level `unsupported/` directory was renamed to `contrib/`. Existing
+  user code with `#include <unsupported/Eigen/...>` continues to compile
+  unchanged via forwarding header shims. The CMake subproject label and
+  build-group target were renamed accordingly: `Unsupported` → `Contrib`,
+  `BuildUnsupported` → `BuildContrib`.
+
 ## [5.0.1] - 2025-11-11
 
 A few bug-fixes from the master branch, including
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d5dde5c..1e51946 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -795,6 +795,7 @@
 #==============================================================================
 # Other Build Configurations.
 #==============================================================================
+add_subdirectory(contrib)
 add_subdirectory(unsupported)
 
 if(EIGEN_BUILD_BLAS)
@@ -814,7 +815,7 @@
 endif()
 
 if (PROJECT_IS_TOP_LEVEL)
-  # must be after test and unsupported, for configuring buildtests.in
+  # must be after test and contrib, for configuring buildtests.in
   add_subdirectory(scripts EXCLUDE_FROM_ALL)
   configure_file(scripts/cdashtesting.cmake.in cdashtesting.cmake @ONLY)
 endif()
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2c37898..f3f62b4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -60,22 +60,20 @@
 ctest --test-dir build --parallel --output-on-failure --no-tests=error
 ```
 
-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.
+Other useful targets: `BuildOfficial` (just `test/`), `BuildContrib` (just `contrib/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.
 
 For focused build recipes, test registration, split-test mechanics, and assertion guidance, see
 [`.agents/testing.md`](.agents/testing.md). Packet and accelerator validation is covered by
 [`.agents/simd-gpu.md`](.agents/simd-gpu.md). The checked-out CMake files remain authoritative for current options.
 
 > **In-flight migration:** [MR 2159](https://gitlab.com/libeigen/eigen/-/merge_requests/2159) is migrating the test framework from Eigen's own `EIGEN_DECLARE_TEST` / `CALL_SUBTEST_N` macros to Google Test. Until it lands, write new tests with the existing framework (`test/main.h`, `VERIFY_*`, `EIGEN_DECLARE_TEST`, `ei_add_test` in the matching `CMakeLists.txt`).
->
-> **In-flight rename:** [MR 2522](https://gitlab.com/libeigen/eigen/-/merge_requests/2522) renames the top-level `unsupported/` directory to `contrib/`. Paths in this document follow master (still `unsupported/`); substitute `contrib/` mechanically once it lands.
 
 ## Tests and benchmarks
 
 - **Every new feature lands with tests.** Bug fixes should add a regression test that fails before the fix and passes after.
-- **Performance-sensitive changes land with a benchmark** under `benchmarks/` or `unsupported/benchmarks/`. Don't defer benchmarks to a follow-up MR.
+- **Performance-sensitive changes land with a benchmark** under `benchmarks/` or `contrib/benchmarks/`. Don't defer benchmarks to a follow-up MR.
 - **Cover numerical corner cases**, not just typical inputs: ±0, ±∞, NaN, subnormals, domain boundaries, near-overflow / underflow values. Decomposition and solver tests should exercise ill-conditioned and structured matrices (Hilbert, Vandermonde, rank-deficient, near-singular, Jordan blocks, …). The bar is matching LAPACK on conditioning, pivoting strategy, and backward stability. Standard references: Higham's *Accuracy and Stability of Numerical Algorithms* / *Functions of Matrices*, Golub & van Loan's *Matrix Computations*.
-- **New SIMD intrinsics need a `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`.
+- **New SIMD intrinsics need a `test/packetmath.cpp` entry** (or `contrib/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`.
 - **Benchmarking discipline.** Benchmarks on a loaded system are meaningless. Before running one: check `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.
 
 ## Coding standards
@@ -83,7 +81,7 @@
 Eigen has a few hard rules that catch contributors most often. The repository-wide rules are in
 [`AGENTS.md`](AGENTS.md#non-negotiable-rules), which also routes to task-specific guidance. The short version:
 
-1. **Header-only contract.** Never `#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`, …).
+1. **Header-only contract.** Never `#include` anything under `Eigen/src/...` or `contrib/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`, …).
 2. **Preserve `EIGEN_DEVICE_FUNC`** on coefficient-level methods. Dropping it silently breaks CUDA / HIP / SYCL builds and rarely shows up in local testing.
 3. **Format with `clang-format-17` exactly** — Google base, 120 columns, configured in `.clang-format`. Newer or older
    `clang-format` will diff against CI. CI checks changed lines (`git clang-format --diff --commit <base>`), and the
@@ -106,7 +104,7 @@
   `EIGEN_STATIC_ASSERT_*` helper or `EIGEN_STATIC_ASSERT(cond, MSG_TOKEN)` to honor `EIGEN_NO_STATIC_ASSERT` and user
   overrides. Use `static_assert(cond, "message")` for unconditional implementation invariants.
 
-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.
+The canonical class layout is visible in recent additions such as `contrib/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.
 
 ### License and SPDX/REUSE headers
 
@@ -182,9 +180,9 @@
 
 ## Load-bearing modules
 
-Some "unsupported" modules carry stability guarantees beyond what the name suggests:
+Some `contrib/` modules carry stability guarantees beyond what the directory 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.
+- **`contrib/Eigen/Tensor`** and **`Eigen/ThreadPool`** together form TensorFlow's core compute backend. The `contrib/` location 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 `contrib/test/tensor_*` before submitting, and call out any behaviour change prominently in the MR description.
 
 ## Communication
 
diff --git a/CTestConfig.cmake b/CTestConfig.cmake
index c2ef438..cca380b 100644
--- a/CTestConfig.cmake
+++ b/CTestConfig.cmake
@@ -15,5 +15,5 @@
 set(CTEST_DROP_SITE_CDASH TRUE)
 #set(CTEST_PROJECT_SUBPROJECTS
 #Official
-#Unsupported
+#Contrib
 #)
diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h
index 33d14c4..8135342 100644
--- a/Eigen/src/Core/MatrixBase.h
+++ b/Eigen/src/Core/MatrixBase.h
@@ -463,19 +463,19 @@
   ///////// MatrixFunctions module /////////
 
   using StemFunction = typename internal::stem_function<Scalar>::type;
-#define EIGEN_MATRIX_FUNCTION(ReturnType, Name, Description)                                                        \
-  /** \returns an expression of the matrix Description of \c *this. \brief This function requires the <a            \
-   * href="unsupported/group__MatrixFunctions__Module.html"> unsupported MatrixFunctions module</a>. To compute the \
-   * coefficient-wise Description use ArrayBase::##Name . */                                                        \
+#define EIGEN_MATRIX_FUNCTION(ReturnType, Name, Description)                                                \
+  /** \returns an expression of the matrix Description of \c *this. \brief This function requires the <a    \
+   * href="contrib/group__MatrixFunctions__Module.html"> contrib MatrixFunctions module</a>. To compute the \
+   * coefficient-wise Description use ArrayBase::##Name . */                                                \
   const ReturnType<Derived> Name() const;
-#define EIGEN_MATRIX_FUNCTION_1(ReturnType, Name, Description, Argument)                                            \
-  /** \returns an expression of the matrix Description of \c *this. \brief This function requires the <a            \
-   * href="unsupported/group__MatrixFunctions__Module.html"> unsupported MatrixFunctions module</a>. To compute the \
-   * coefficient-wise Description use ArrayBase::##Name . */                                                        \
+#define EIGEN_MATRIX_FUNCTION_1(ReturnType, Name, Description, Argument)                                    \
+  /** \returns an expression of the matrix Description of \c *this. \brief This function requires the <a    \
+   * href="contrib/group__MatrixFunctions__Module.html"> contrib MatrixFunctions module</a>. To compute the \
+   * coefficient-wise Description use ArrayBase::##Name . */                                                \
   const ReturnType<Derived> Name(Argument) const;
 
   EIGEN_MATRIX_FUNCTION(MatrixExponentialReturnValue, exp, exponential)
-  /** \brief Helper function for the <a href="unsupported/group__MatrixFunctions__Module.html"> unsupported
+  /** \brief Helper function for the <a href="contrib/group__MatrixFunctions__Module.html"> contrib
    * MatrixFunctions module</a>.*/
   const MatrixFunctionReturnValue<Derived> matrixFunction(StemFunction f) const;
   EIGEN_MATRIX_FUNCTION(MatrixFunctionReturnValue, cosh, hyperbolic cosine)
diff --git a/Eigen/src/Core/arch/Default/BFloat16.h b/Eigen/src/Core/arch/Default/BFloat16.h
index 042e955..764e6af 100644
--- a/Eigen/src/Core/arch/Default/BFloat16.h
+++ b/Eigen/src/Core/arch/Default/BFloat16.h
@@ -59,7 +59,7 @@
   BF16_PACKET_FUNCTION(PACKET_F, PACKET_BF16, psqrt)                     \
   BF16_PACKET_FUNCTION(PACKET_F, PACKET_BF16, ptanh)
 
-// BF16 wrappers for unsupported/SpecialFunctions.
+// BF16 wrappers for contrib/SpecialFunctions.
 #define EIGEN_INSTANTIATE_SPECIAL_FUNCS_BF16(PACKET_F, PACKET_BF16) \
   BF16_PACKET_FUNCTION(PACKET_F, PACKET_BF16, perf)                 \
   BF16_PACKET_FUNCTION(PACKET_F, PACKET_BF16, pndtri)
diff --git a/Eigen/src/Core/arch/Default/Half.h b/Eigen/src/Core/arch/Default/Half.h
index c9f6472..a628230 100644
--- a/Eigen/src/Core/arch/Default/Half.h
+++ b/Eigen/src/Core/arch/Default/Half.h
@@ -78,7 +78,7 @@
   F16_PACKET_FUNCTION(PACKET_F, PACKET_F16, psqrt)                     \
   F16_PACKET_FUNCTION(PACKET_F, PACKET_F16, ptanh)
 
-// F16 wrappers for unsupported/SpecialFunctions.
+// F16 wrappers for contrib/SpecialFunctions.
 #define EIGEN_INSTANTIATE_SPECIAL_FUNCS_F16(PACKET_F, PACKET_F16) \
   F16_PACKET_FUNCTION(PACKET_F, PACKET_F16, perf)                 \
   F16_PACKET_FUNCTION(PACKET_F, PACKET_F16, pndtri)
diff --git a/Eigen/src/Core/util/GpuHipCudaDefines.inc b/Eigen/src/Core/util/GpuHipCudaDefines.inc
index a09c8da..1c0fbba 100644
--- a/Eigen/src/Core/util/GpuHipCudaDefines.inc
+++ b/Eigen/src/Core/util/GpuHipCudaDefines.inc
@@ -16,11 +16,11 @@
 // There is code in the Tensorflow codebase that will define EIGEN_USE_GPU,  but
 // for some reason gets sent to the gcc/host compiler instead of the gpu/nvcc/hipcc compiler
 // When compiling such files, gcc will end up trying to pick up the CUDA headers by
-// default (see the code within "unsupported/Eigen/Tensor" that is guarded by EIGEN_USE_GPU)
+// default (see the code within "contrib/Eigen/Tensor" that is guarded by EIGEN_USE_GPU)
 // This will obviously not work when trying to compile tensorflow on a system with no CUDA
 // To work around this issue for HIP systems (and leave the default behaviour intact), the
 // HIP tensorflow build defines EIGEN_USE_HIP when compiling all source files, and
-// "unsupported/Eigen/Tensor" has been updated to use HIP header when EIGEN_USE_HIP is
+// "contrib/Eigen/Tensor" has been updated to use HIP header when EIGEN_USE_HIP is
 // defined. In continuation of that requirement, the guard here needs to be EIGEN_USE_HIP as well
 
 #if defined(EIGEN_USE_HIP)
diff --git a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
index c79acca..2a8b148 100644
--- a/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
+++ b/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
@@ -343,7 +343,7 @@
    * Example: \include SelfAdjointEigenSolver_operatorSqrt.cpp
    * Output: \verbinclude SelfAdjointEigenSolver_operatorSqrt.out
    *
-   * \sa operatorInverseSqrt(), <a href="unsupported/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
+   * \sa operatorInverseSqrt(), <a href="contrib/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
    */
   EIGEN_DEVICE_FUNC MatrixType operatorSqrt() const {
     eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
@@ -359,7 +359,7 @@
    * have been computed before.
    *
    * \sa operatorInverseSqrt(), operatorSqrt(),
-   * <a href="unsupported/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
+   * <a href="contrib/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
    */
   EIGEN_DEVICE_FUNC MatrixType operatorExp() const {
     eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
@@ -383,7 +383,7 @@
    * Output: \verbinclude SelfAdjointEigenSolver_operatorInverseSqrt.out
    *
    * \sa operatorSqrt(), MatrixBase::inverse(), <a
-   * href="unsupported/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
+   * href="contrib/group__MatrixFunctions__Module.html">MatrixFunctions Module</a>
    */
   EIGEN_DEVICE_FUNC MatrixType operatorInverseSqrt() const {
     eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized.");
diff --git a/Eigen/src/plugins/ArrayCwiseUnaryOps.inc b/Eigen/src/plugins/ArrayCwiseUnaryOps.inc
index c8890ac..4bfbd46 100644
--- a/Eigen/src/plugins/ArrayCwiseUnaryOps.inc
+++ b/Eigen/src/plugins/ArrayCwiseUnaryOps.inc
@@ -36,7 +36,7 @@
 /** \returns an expression of the coefficient-wise exponential of *this.
  *
  * This function computes the coefficient-wise exponential. The function MatrixBase::exp() in the
- * unsupported module MatrixFunctions computes the matrix exponential.
+ * contrib module MatrixFunctions computes the matrix exponential.
  *
  * Example: \include Cwise_exp.cpp
  * Output: \verbinclude Cwise_exp.out
@@ -83,7 +83,7 @@
 /** \returns an expression of the coefficient-wise logarithm of *this.
  *
  * This function computes the coefficient-wise logarithm. The function MatrixBase::log() in the
- * unsupported module MatrixFunctions computes the matrix logarithm.
+ * contrib module MatrixFunctions computes the matrix logarithm.
  *
  * Example: \include Cwise_log.cpp
  * Output: \verbinclude Cwise_log.out
@@ -122,7 +122,7 @@
 /** \returns an expression of the coefficient-wise square root of *this.
  *
  * This function computes the coefficient-wise square root. The function MatrixBase::sqrt() in the
- * unsupported module MatrixFunctions computes the matrix square root.
+ * contrib module MatrixFunctions computes the matrix square root.
  *
  * Example: \include Cwise_sqrt.cpp
  * Output: \verbinclude Cwise_sqrt.out
@@ -167,7 +167,7 @@
 /** \returns an expression of the coefficient-wise cosine of *this.
  *
  * This function computes the coefficient-wise cosine. The function MatrixBase::cos() in the
- * unsupported module MatrixFunctions computes the matrix cosine.
+ * contrib module MatrixFunctions computes the matrix cosine.
  *
  * Example: \include Cwise_cos.cpp
  * Output: \verbinclude Cwise_cos.out
@@ -179,7 +179,7 @@
 /** \returns an expression of the coefficient-wise sine of *this.
  *
  * This function computes the coefficient-wise sine. The function MatrixBase::sin() in the
- * unsupported module MatrixFunctions computes the matrix sine.
+ * contrib module MatrixFunctions computes the matrix sine.
  *
  * Example: \include Cwise_sin.cpp
  * Output: \verbinclude Cwise_sin.out
@@ -559,7 +559,7 @@
  * \param exponent the scalar exponent value.
  *
  * This function computes the coefficient-wise power. The function MatrixBase::pow() in the
- * unsupported module MatrixFunctions computes the matrix power.
+ * contrib module MatrixFunctions computes the matrix power.
  *
  * Example: \include Cwise_pow.cpp
  * Output: \verbinclude Cwise_pow.out
diff --git a/INSTALL b/INSTALL
index 4f717e9..9a76a9b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -13,7 +13,7 @@
 
 You can use right away the headers in the Eigen/ subdirectory. In order
 to install, just copy this Eigen/ subdirectory to your favorite location.
-If you also want the unsupported features, copy the unsupported/
+If you also want the contrib features, copy the contrib/
 subdirectory too.
 
 Method 2. Installing using CMake
diff --git a/REUSE.toml b/REUSE.toml
index 6c8d1fa..0ee9e19 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -69,7 +69,7 @@
 SPDX-License-Identifier = "BSD-3-Clause"
 
 [[annotations]]
-path = "unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt"
+path = "contrib/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt"
 SPDX-FileCopyrightText = [
     "Jorge More - Argonne National Laboratory",
     "Burt Garbow - Argonne National Laboratory",
diff --git a/benchmarks/Core/bench_cwise_math.cpp b/benchmarks/Core/bench_cwise_math.cpp
index 6480770..34b0ba6 100644
--- a/benchmarks/Core/bench_cwise_math.cpp
+++ b/benchmarks/Core/bench_cwise_math.cpp
@@ -7,7 +7,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/SpecialFunctions>
+#include <contrib/Eigen/SpecialFunctions>
 
 using namespace Eigen;
 
diff --git a/benchmarks/FFT/bench_fft.cpp b/benchmarks/FFT/bench_fft.cpp
index deac650..3a53b36 100644
--- a/benchmarks/FFT/bench_fft.cpp
+++ b/benchmarks/FFT/bench_fft.cpp
@@ -3,7 +3,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/FFT>
+#include <contrib/Eigen/FFT>
 #include <complex>
 #include <vector>
 
diff --git a/ci/build.linux.gitlab-ci.yml b/ci/build.linux.gitlab-ci.yml
index 9140b92..5033588 100644
--- a/ci/build.linux.gitlab-ci.yml
+++ b/ci/build.linux.gitlab-ci.yml
@@ -116,7 +116,7 @@
   variables:
     EIGEN_CI_ADDITIONAL_ARGS: "-DEIGEN_TEST_AVX512DQ=on"
 
-# AVX512-FP16 builds are split into official/unsupported because building all
+# AVX512-FP16 builds are split into official/contrib because building all
 # tests exceeds the 3-hour GitLab SaaS shared-runner timeout.
 .build:linux:cross:x86-64:gcc-13:avx512fp16:
   extends: build:linux:cross:x86-64:gcc-13:default
@@ -133,10 +133,10 @@
   variables:
     EIGEN_CI_BUILD_TARGET: BuildOfficial
 
-build:linux:cross:x86-64:gcc-13:avx512fp16:unsupported:
+build:linux:cross:x86-64:gcc-13:avx512fp16:contrib:
   extends: .build:linux:cross:x86-64:gcc-13:avx512fp16
   variables:
-    EIGEN_CI_BUILD_TARGET: BuildUnsupported
+    EIGEN_CI_BUILD_TARGET: BuildContrib
 
 # Clang-14 (stable recent version)
 build:linux:cross:x86-64:clang-14:default:
@@ -206,7 +206,7 @@
 
 ######## Sanitizers ############################################################
 
-# ASAN/UBSAN builds are split into official/unsupported because the
+# ASAN/UBSAN builds are split into official/contrib because the
 # instrumented executables are too large to upload as a single artifact.
 .build:linux:cross:x86-64:clang-19:default:asan-ubsan:
   extends: .build:linux:cross:x86-64
@@ -235,17 +235,17 @@
   variables:
     EIGEN_CI_BUILD_TARGET: BuildOfficial
 
-build:linux:cross:x86-64:clang-19:default:asan-ubsan:unsupported:
+build:linux:cross:x86-64:clang-19:default:asan-ubsan:contrib:
   extends: .build:linux:cross:x86-64:clang-19:default:asan-ubsan
   variables:
-    EIGEN_CI_BUILD_TARGET: BuildUnsupported
+    EIGEN_CI_BUILD_TARGET: BuildContrib
 
 ######## NVHPC #################################################################
 
 # NVHPC (nvc++) uses NVIDIA's HPC SDK container image with the compilers
 # pre-installed. We override EIGEN_CI_INSTALL to avoid trying to apt-get
 # install the compiler.
-# Split into official/unsupported because nvc++ is so slow that the full
+# Split into official/contrib because nvc++ is so slow that the full
 # build exceeds the 3-hour GitLab SaaS shared-runner timeout.
 .build:linux:x86-64:nvhpc-26.1:
   extends: .build:linux:cross:x86-64
@@ -283,10 +283,10 @@
   variables:
     EIGEN_CI_BUILD_TARGET: BuildOfficial
 
-build:linux:x86-64:nvhpc-26.1:default:unsupported:
+build:linux:x86-64:nvhpc-26.1:default:contrib:
   extends: .build:linux:x86-64:nvhpc-26.1
   variables:
-    EIGEN_CI_BUILD_TARGET: BuildUnsupported
+    EIGEN_CI_BUILD_TARGET: BuildContrib
 
 ######## CUDA ##################################################################
 
@@ -524,7 +524,7 @@
     EIGEN_CI_CROSS_CXX_COMPILER: aarch64-linux-gnu-g++-14
 
 # Full nightly SME coverage: compile the *entire* test suite (buildtests, both
-# Official and Unsupported) under +sme2, not just the SME-relevant targets. This
+# Official and Contrib) under +sme2, not just the SME-relevant targets. This
 # is what treats SME "as any other platform": it catches any compile breakage
 # under the streaming-mode flags across the whole codebase -- e.g. the tensor-
 # contraction packer path that only surfaces once TensorContraction is built
@@ -532,7 +532,7 @@
 # MRs via the inherited .rules:libeigen:all-tests; the per-SVL subset build
 # above stays as the fast, cheap signal. Cross-building every test under the SME
 # flags is slow -- the raised timeout is a starting estimate; tune it once a
-# real run establishes the wall-clock (drop to BuildOfficial/BuildUnsupported
+# real run establishes the wall-clock (drop to BuildOfficial/BuildContrib
 # split builds if a single job overruns).
 build:linux:cross:sme:gcc-14:full:
   extends: .build:linux:cross:sme
@@ -625,7 +625,7 @@
     # with SVE2 enabled, GCC 13 through 15 emit `whilewr p0.b, wzr, wzr` for the
     # autovectorizer's alias checks, using 32-bit W registers where the
     # instruction takes X registers, and the assembler rejects it. It reproduces
-    # at every vector length from 256 up (unsupported/test/tensor_block_eval.cpp
+    # at every vector length from 256 up (contrib/test/tensor_block_eval.cpp
     # is one trigger) and is a GCC bug, not an Eigen one; clang is unaffected.
     EIGEN_CI_ADDITIONAL_ARGS: >-
       -DEIGEN_TEST_SVE=ON
@@ -935,10 +935,10 @@
     EIGEN_CI_CCACHE_POOL: build-linux-cross-x86-64-gcc-13-avx512fp16-official
   rules: !reference [.rules:libeigen:affected-tests:avx512fp16, rules]
 
-build:linux:cross:x86-64:gcc-13:avx512fp16:unsupported:affected:
-  extends: build:linux:cross:x86-64:gcc-13:avx512fp16:unsupported
+build:linux:cross:x86-64:gcc-13:avx512fp16:contrib:affected:
+  extends: build:linux:cross:x86-64:gcc-13:avx512fp16:contrib
   variables:
-    EIGEN_CI_CCACHE_POOL: build-linux-cross-x86-64-gcc-13-avx512fp16-unsupported
+    EIGEN_CI_CCACHE_POOL: build-linux-cross-x86-64-gcc-13-avx512fp16-contrib
   rules: !reference [.rules:libeigen:affected-tests:avx512fp16, rules]
 
 # 32-bit arm: a distinct NEON code path from the aarch64 job above.
diff --git a/ci/common.gitlab-ci.yml b/ci/common.gitlab-ci.yml
index 05a2039..6c48092 100644
--- a/ci/common.gitlab-ci.yml
+++ b/ci/common.gitlab-ci.yml
@@ -84,9 +84,9 @@
         - test/gpu_common.h
         - test/gpu_test_helper.h
         - test/main.h
-        - unsupported/Eigen/src/Tensor/*Gpu*.h
-        - unsupported/test/*.cu
-        - unsupported/test/GPU/**/*
+        - contrib/Eigen/src/Tensor/*Gpu*.h
+        - contrib/test/*.cu
+        - contrib/test/GPU/**/*
     # `gpu-tests` is the platform label for GPU and already stands alone above,
     # so it composes with `affected-tests` without another entry.  It is also
     # why `all-platforms` covers no GPU job, and none of the compile-only sets
diff --git a/ci/scripts/run-clang-tidy.sh b/ci/scripts/run-clang-tidy.sh
index cb67b03..174cd1b 100755
--- a/ci/scripts/run-clang-tidy.sh
+++ b/ci/scripts/run-clang-tidy.sh
@@ -87,7 +87,7 @@
   # Restrict to header files inside the src trees.
   if [[ "${header}" =~ ^Eigen/src/([^/]+)/ ]]; then
     module="${BASH_REMATCH[1]}"
-  elif [[ "${header}" =~ ^unsupported/Eigen/src/([^/]+)/ ]]; then
+  elif [[ "${header}" =~ ^contrib/Eigen/src/([^/]+)/ ]]; then
     module="${BASH_REMATCH[1]}"
   else
     return 1
@@ -112,8 +112,8 @@
   # nested deeper than the module's top-level src/ (e.g. arch-specific
   # backends under Eigen/src/Core/arch/<ISA>/) that don't carry their own
   # `#error` directive.
-  if [[ "${header}" =~ ^unsupported/ ]]; then
-    hint="unsupported/Eigen/${module}"
+  if [[ "${header}" =~ ^contrib/ ]]; then
+    hint="contrib/Eigen/${module}"
   else
     hint="Eigen/${module}"
   fi
@@ -184,7 +184,7 @@
   # quoted third-party include in the tree is reachable without an
   # EIGEN_USE_* macro this job does not define.
   case "${spelling}" in
-    Eigen/*|unsupported/*|./*|../*) return 0 ;;
+    Eigen/*|contrib/*|unsupported/*|./*|../*) return 0 ;;
   esac
   directive=$(sed -n "${location##*:}p" "${location%:*}" 2>/dev/null)
   if [[ "${directive}" =~ ^[[:space:]]*#[[:space:]]*include[[:space:]]*\" ]]; then
diff --git a/ci/test.linux.gitlab-ci.yml b/ci/test.linux.gitlab-ci.yml
index 0216528..9074744 100644
--- a/ci/test.linux.gitlab-ci.yml
+++ b/ci/test.linux.gitlab-ci.yml
@@ -50,10 +50,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:gcc-10:default:unsupported:
+test:linux:x86-64:gcc-10:default:contrib:
   extends: .test:linux:x86-64:gcc-10:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:x86-64:gcc-10:avx:
   extends: .test:linux:x86-64
@@ -66,10 +66,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:gcc-10:avx:unsupported:
+test:linux:x86-64:gcc-10:avx:contrib:
   extends: .test:linux:x86-64:gcc-10:avx
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:x86-64:gcc-10:avx2:
   extends: .test:linux:x86-64
@@ -82,10 +82,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:gcc-10:avx2:unsupported:
+test:linux:x86-64:gcc-10:avx2:contrib:
   extends: .test:linux:x86-64:gcc-10:avx2
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:x86-64:gcc-10:avx512dq:
   extends: .test:linux:x86-64
@@ -103,10 +103,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:gcc-10:avx512dq:unsupported:
+test:linux:x86-64:gcc-10:avx512dq:contrib:
   extends: .test:linux:x86-64:gcc-10:avx512dq
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 # GCC-13 for AVX512-FP16 (_Float16 support).
 .test:linux:x86-64:gcc-13:default:
@@ -116,7 +116,7 @@
     EIGEN_CI_INSTALL: g++-13
 
 # The corresponding test jobs (test:linux:x86-64:gcc-13:avx512fp16:{official,
-# unsupported}) are intentionally omitted: we do not currently have a runner
+# contrib}) are intentionally omitted: we do not currently have a runner
 # whose CPU supports AVX512-FP16, so running them produces wholesale SIGILL
 # failures.  The build:linux:cross:x86-64:gcc-13:avx512fp16:* jobs remain so
 # that AVX512-FP16 code paths are still compile-checked.
@@ -133,10 +133,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:clang-14:default:unsupported:
+test:linux:x86-64:clang-14:default:contrib:
   extends: .test:linux:x86-64:clang-14:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:x86-64:clang-14:avx2:
   extends: .test:linux:x86-64
@@ -149,10 +149,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:clang-14:avx2:unsupported:
+test:linux:x86-64:clang-14:avx2:contrib:
   extends: .test:linux:x86-64:clang-14:avx2
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:x86-64:clang-14:avx512dq:
   extends: .test:linux:x86-64
@@ -170,10 +170,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:clang-14:avx512dq:unsupported:
+test:linux:x86-64:clang-14:avx512dq:contrib:
   extends: .test:linux:x86-64:clang-14:avx512dq
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 # Generic vector extension backend.
 .test:linux:x86-64:clang-19:generic:avx512dq:
@@ -192,10 +192,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:clang-19:generic:avx512dq:unsupported:
+test:linux:x86-64:clang-19:generic:avx512dq:contrib:
   extends: .test:linux:x86-64:clang-19:generic:avx512dq
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:x86-64:clang-19:cxx20:nightly:
   extends: .test:linux:x86-64
@@ -213,10 +213,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:clang-19:cxx20:nightly:unsupported:
+test:linux:x86-64:clang-19:cxx20:nightly:contrib:
   extends: .test:linux:x86-64:clang-19:cxx20:nightly
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### Sanitizers ###############################################################
 
@@ -236,11 +236,11 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:clang-19:default:asan-ubsan:unsupported:
+test:linux:x86-64:clang-19:default:asan-ubsan:contrib:
   extends: .test:linux:x86-64:clang-19:default:asan-ubsan
-  needs: [ build:linux:cross:x86-64:clang-19:default:asan-ubsan:unsupported ]
+  needs: [ build:linux:cross:x86-64:clang-19:default:asan-ubsan:contrib ]
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### NVHPC ####################################################################
 
@@ -259,11 +259,11 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:x86-64:nvhpc-26.1:default:unsupported:
+test:linux:x86-64:nvhpc-26.1:default:contrib:
   extends: .test:linux:x86-64:nvhpc-26.1:default
-  needs: [ build:linux:x86-64:nvhpc-26.1:default:unsupported ]
+  needs: [ build:linux:x86-64:nvhpc-26.1:default:contrib ]
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### CUDA #####################################################################
 .test:linux:cuda:
@@ -404,10 +404,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:arm:gcc-10:default:unsupported:
+test:linux:arm:gcc-10:default:contrib:
   extends: .test:linux:arm:gcc-10:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:arm:clang-14:default:
   extends: .test:linux:arm
@@ -420,10 +420,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:arm:clang-14:default:unsupported:
+test:linux:arm:clang-14:default:contrib:
   extends: .test:linux:arm:clang-14:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### SME ######################################################################
 
@@ -522,13 +522,13 @@
     QEMU_CPU: max,sme=on,sme512=on,sme128=off,sme256=off,sme1024=off,sme2048=off
     EIGEN_CI_CTEST_REGEX: product_sme
 
-# Full nightly SME test run: the complete Official + Unsupported ctest suite
+# Full nightly SME test run: the complete Official + Contrib ctest suite
 # against the full build above, at a single representative SVL (512: the logical
 # block matches the ZA tile grid exactly, exercising the multi-vector-load fast
 # path in sme_process). Cross-SVL geometry is already covered by the per-SVL
 # product_* subset jobs above, so one SVL is enough for the full run. Extends
 # ...:default (not ...:default:official) so no product_* CTEST_REGEX is
-# inherited -- these select by label instead. Official/Unsupported are split
+# inherited -- these select by label instead. Official/Contrib are split
 # into two jobs, and Official is sharded further below. The 3h job timeout is
 # the GitLab SaaS hosted-runner maximum (a slow host overran 2h). Inherits
 # .rules:libeigen:all-tests, so it runs on the nightly schedule and on
@@ -550,10 +550,10 @@
     # Overriding EIGEN_CI_CTEST_ARGS replaces the whole value; restate --timeout.
     EIGEN_CI_CTEST_ARGS: --timeout 3000 -I $CI_NODE_INDEX,,$CI_NODE_TOTAL
 
-test:linux:sme512:gcc-14:full:unsupported:
+test:linux:sme512:gcc-14:full:contrib:
   extends: .test:linux:sme512:gcc-14:full
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
     # tensor_thread_pool: threaded tests are useless under single-threaded TCG
     # (same exclusion as .test:linux:qemu). FFT: overruns even the raised 3000s
     # timeout under TCG at EIGEN_REPEAT=2; it is kissfft-based scalar/complex
@@ -586,10 +586,10 @@
     # Threaded tests are meaningless under single-threaded TCG, and FFT overruns
     # even the raised timeout at EIGEN_REPEAT=2 -- it is kissfft-based scalar and
     # complex code with no SVE-specific path, and every native job covers it.
-    # On the anchor rather than the :unsupported jobs so the affected-tier jobs,
+    # On the anchor rather than the :contrib jobs so the affected-tier jobs,
     # which apply no label filter and so run both labels in one pass, inherit it
     # too; the :official jobs are unaffected either way, as both names are
-    # Unsupported tests.
+    # Contrib tests.
     EIGEN_CI_CTEST_EXCLUDE: tensor_thread_pool|FFT
     # Name the compiler the artifacts were built with, not the default-version
     # cross g++. The test stage does compile: the failtest targets are
@@ -598,7 +598,7 @@
     # without that exact binary fails all 62 failtests at once -- and the _ko
     # halves then pass vacuously, WILL_FAIL being unable to tell the asserted
     # compile error from a missing compiler. Only the affected tier sees this:
-    # the :official and :unsupported jobs filter by label, and failtests carry
+    # the :official and :contrib jobs filter by label, and failtests carry
     # neither label. (The buildsystem scenarios, which bake in the same path,
     # no longer register here: test/buildsystem/CMakeLists.txt skips emulator
     # builds, whose consumer binaries cannot run on the host.)
@@ -642,30 +642,30 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:sve128:gcc-13:unsupported:
+test:linux:sve128:gcc-13:contrib:
   extends: .test:linux:sve:vl128
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 test:linux:sve256:gcc-13:official:
   extends: .test:linux:sve:vl256
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:sve256:gcc-13:unsupported:
+test:linux:sve256:gcc-13:contrib:
   extends: .test:linux:sve:vl256
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 test:linux:sve512:gcc-13:official:
   extends: .test:linux:sve:vl512
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:sve512:gcc-13:unsupported:
+test:linux:sve512:gcc-13:contrib:
   extends: .test:linux:sve:vl512
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### aarch64 ##################################################################
 
@@ -688,10 +688,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:aarch64:gcc-10:default:unsupported:
+test:linux:aarch64:gcc-10:default:contrib:
   extends: .test:linux:aarch64:gcc-10:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:aarch64:clang-14:default:
   extends: .test:linux:aarch64
@@ -704,10 +704,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:aarch64:clang-14:default:unsupported:
+test:linux:aarch64:clang-14:default:contrib:
   extends: .test:linux:aarch64:clang-14:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### ppc64le ##################################################################
 
@@ -728,10 +728,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:ppc64le:gcc-14:default:unsupported:
+test:linux:ppc64le:gcc-14:default:contrib:
   extends: .test:linux:ppc64le:gcc-14:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:ppc64le:clang-16:default:
   extends: .test:linux:ppc64le
@@ -744,10 +744,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:ppc64le:clang-16:default:unsupported:
+test:linux:ppc64le:clang-16:default:contrib:
   extends: .test:linux:ppc64le:clang-16:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### loongarch64 ##############################################################
 
@@ -768,10 +768,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:loongarch64:gcc-14:default:unsupported:
+test:linux:loongarch64:gcc-14:default:contrib:
   extends: .test:linux:loongarch64:gcc-14:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 ##### riscv64 ##################################################################
 
@@ -796,10 +796,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:riscv64:gcc-15:default:unsupported:
+test:linux:riscv64:gcc-15:default:contrib:
   extends: .test:linux:riscv64:gcc-15:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:linux:riscv64:clang-21:default:
   extends: .test:linux:riscv64
@@ -812,10 +812,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:linux:riscv64:clang-21:default:unsupported:
+test:linux:riscv64:clang-21:default:contrib:
   extends: .test:linux:riscv64:clang-21:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 # Unlike the other smoke jobs, these two are namespace-guarded: they inherit
 # `tags: [riscv]` from .test:linux:riscv64, a single self-hosted machine that
@@ -939,6 +939,7 @@
         - Eigen/Version
         - blas/CMakeLists.txt
         - lapack/CMakeLists.txt
+        - contrib/**/CMakeLists.txt
         - unsupported/**/CMakeLists.txt
         - doc/CMakeLists.txt
         - doc/TopicCMakeGuide.dox
@@ -957,7 +958,7 @@
 ##### MR Affected Tests ########################################################
 # Paired with the affected build jobs.  No CTest label is set: the regex from
 # select:tests is the only filter, so a selection spanning Official and
-# Unsupported tests runs in one job.
+# Contrib tests runs in one job.
 #
 # Each job shares its trigger rule with the build job it needs; see
 # .rules:libeigen:affected-tests:* in ci/common.gitlab-ci.yml.
diff --git a/ci/test.windows.gitlab-ci.yml b/ci/test.windows.gitlab-ci.yml
index 32b185b..d1c7639 100644
--- a/ci/test.windows.gitlab-ci.yml
+++ b/ci/test.windows.gitlab-ci.yml
@@ -29,10 +29,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:windows:x86-64:msvc-14.29:default:unsupported:
+test:windows:x86-64:msvc-14.29:default:contrib:
   extends: .test:windows:x86-64:msvc-14.29:default
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:windows:x86-64:msvc-14.29:avx2:
   extends: .test:windows
@@ -43,10 +43,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:windows:x86-64:msvc-14.29:avx2:unsupported:
+test:windows:x86-64:msvc-14.29:avx2:contrib:
   extends: .test:windows:x86-64:msvc-14.29:avx2
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 .test:windows:x86-64:msvc-14.29:avx512dq:
   extends: .test:windows
@@ -62,10 +62,10 @@
   variables:
     EIGEN_CI_CTEST_LABEL: Official
 
-test:windows:x86-64:msvc-14.29:avx512dq:unsupported:
+test:windows:x86-64:msvc-14.29:avx512dq:contrib:
   extends: .test:windows:x86-64:msvc-14.29:avx512dq
   variables:
-    EIGEN_CI_CTEST_LABEL: Unsupported
+    EIGEN_CI_CTEST_LABEL: Contrib
 
 # MSVC 14.29 (VS 2019) + CUDA
 
@@ -93,7 +93,7 @@
 ##### MR Affected Tests ########################################################
 # Paired with the affected Windows build job.  No CTest label is set: the regex
 # from select:tests is the only filter, so a selection spanning Official and
-# Unsupported tests runs in one job rather than the two the labelled jobs above
+# Contrib tests runs in one job rather than the two the labelled jobs above
 # need.
 #
 # Dropping the label filter is what makes the exclusion below necessary.  The
diff --git a/cmake/EigenConfigureTesting.cmake b/cmake/EigenConfigureTesting.cmake
index d19c27a..4638c26 100644
--- a/cmake/EigenConfigureTesting.cmake
+++ b/cmake/EigenConfigureTesting.cmake
@@ -14,15 +14,15 @@
 add_custom_target(buildtests)
 
 # buildsmoketests is created up-front so that ei_add_test_internal — which
-# runs from inside test/ and unsupported/test/ — can attach the smoketest
+# runs from inside test/ and contrib/test/ — can attach the smoketest
 # label and the build dependency in the same directory scope where add_test()
 # was called.  CMake's set_property(TEST ...) and add_dependencies require
 # this scope match, so a single post-hoc registration from the top level
-# would silently fail for unsupported entries.
+# would silently fail for contrib entries.
 add_custom_target(buildsmoketests)
 
 # Load the smoke-test list once.  ei_smoke_test_list is then visible to both
-# test/ and unsupported/test/ as a parent-scope variable, and ei_add_test_internal
+# test/ and contrib/test/ as a parent-scope variable, and ei_add_test_internal
 # checks it on every test it registers.
 include(EigenSmokeTestList)
 
diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt
new file mode 100644
index 0000000..48c5033
--- /dev/null
+++ b/contrib/CMakeLists.txt
@@ -0,0 +1,14 @@
+# SPDX-FileCopyrightText: The Eigen Authors
+# SPDX-License-Identifier: MPL-2.0
+
+add_subdirectory(Eigen)
+if(EIGEN_BUILD_DOC)
+  add_subdirectory(doc EXCLUDE_FROM_ALL)
+endif()
+if(EIGEN_BUILD_TESTING)
+  if(EIGEN_LEAVE_TEST_IN_ALL_TARGET)
+    add_subdirectory(test) # CTest automatic test building relies on the "all" target.
+  else()
+    add_subdirectory(test EXCLUDE_FROM_ALL)
+  endif()
+endif()
diff --git a/contrib/Eigen/AdolcForward b/contrib/Eigen/AdolcForward
new file mode 100644
index 0000000..21e2667
--- /dev/null
+++ b/contrib/Eigen/AdolcForward
@@ -0,0 +1,158 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// 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
+
+#ifndef EIGEN_ADOLC_FORWARD_MODULE_H
+#define EIGEN_ADOLC_FORWARD_MODULE_H
+
+//--------------------------------------------------------------------------------
+//
+// This file provides support for adolc's adouble type in forward mode.
+// ADOL-C is a C++ automatic differentiation library,
+// see https://projects.coin-or.org/ADOL-C for more information.
+//
+// Note that the maximal number of directions is controlled by
+// the preprocessor token NUMBER_DIRECTIONS. The default is 2.
+//
+//--------------------------------------------------------------------------------
+
+#define ADOLC_TAPELESS
+#ifndef NUMBER_DIRECTIONS
+#define NUMBER_DIRECTIONS 2
+#endif
+#include <adolc/adtl.h>
+
+// adolc defines some very stupid macros:
+#if defined(malloc)
+#undef malloc
+#endif
+
+#if defined(calloc)
+#undef calloc
+#endif
+
+#if defined(realloc)
+#undef realloc
+#endif
+
+#include "../../Eigen/Core"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/**
+ * \defgroup AdolcForward_Module Adolc forward module
+ * This module provides support for adolc's adouble type in forward mode.
+ * ADOL-C is a C++ automatic differentiation library,
+ * see https://projects.coin-or.org/ADOL-C for more information.
+ * It mainly consists in:
+ *  - a struct Eigen::NumTraits<adtl::adouble> specialization
+ *  - overloads of internal::* math function for adtl::adouble type.
+ *
+ * Note that the maximal number of directions is controlled by
+ * the preprocessor token NUMBER_DIRECTIONS. The default is 2.
+ *
+ * \code
+ * #include <contrib/Eigen/AdolcForward>
+ * \endcode
+ */
+//@{
+
+}  // namespace Eigen
+
+// Eigen's require a few additional functions which must be defined in the same namespace
+// than the custom scalar type own namespace
+namespace adtl {
+
+inline const adouble& conj(const adouble& x) { return x; }
+inline const adouble& real(const adouble& x) { return x; }
+inline adouble imag(const adouble&) { return 0.; }
+inline adouble abs(const adouble& x) { return fabs(x); }
+inline adouble abs2(const adouble& x) { return x * x; }
+
+inline bool(isinf)(const adouble& x) { return (Eigen::numext::isinf)(x.getValue()); }
+inline bool(isnan)(const adouble& x) { return (Eigen::numext::isnan)(x.getValue()); }
+
+}  // namespace adtl
+
+namespace Eigen {
+
+template <>
+struct NumTraits<adtl::adouble> : NumTraits<double> {
+  typedef adtl::adouble Real;
+  typedef adtl::adouble NonInteger;
+  typedef adtl::adouble Nested;
+  enum {
+    IsComplex = 0,
+    IsInteger = 0,
+    IsSigned = 1,
+    RequireInitialization = 1,
+    ReadCost = 1,
+    AddCost = 1,
+    MulCost = 1
+  };
+};
+
+template <typename Functor>
+class AdolcForwardJacobian : public Functor {
+  typedef adtl::adouble ActiveScalar;
+
+ public:
+  AdolcForwardJacobian() : Functor() {}
+  AdolcForwardJacobian(const Functor& f) : Functor(f) {}
+
+  // forward constructors
+  template <typename T0>
+  AdolcForwardJacobian(const T0& a0) : Functor(a0) {}
+  template <typename T0, typename T1>
+  AdolcForwardJacobian(const T0& a0, const T1& a1) : Functor(a0, a1) {}
+  template <typename T0, typename T1, typename T2>
+  AdolcForwardJacobian(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2) {}
+
+  typedef typename Functor::InputType InputType;
+  typedef typename Functor::ValueType ValueType;
+  typedef typename Functor::JacobianType JacobianType;
+
+  typedef Matrix<ActiveScalar, InputType::SizeAtCompileTime, 1> ActiveInput;
+  typedef Matrix<ActiveScalar, ValueType::SizeAtCompileTime, 1> ActiveValue;
+
+  void operator()(const InputType& x, ValueType* v, JacobianType* _jac) const {
+    eigen_assert(v != 0);
+    if (!_jac) {
+      Functor::operator()(x, v);
+      return;
+    }
+
+    JacobianType& jac = *_jac;
+
+    ActiveInput ax = x.template cast<ActiveScalar>();
+    ActiveValue av(jac.rows());
+
+    for (int j = 0; j < jac.cols(); j++)
+      for (int i = 0; i < jac.cols(); i++) ax[i].setADValue(j, i == j ? 1 : 0);
+
+    Functor::operator()(ax, &av);
+
+    for (int i = 0; i < jac.rows(); i++) {
+      (*v)[i] = av[i].getValue();
+      for (int j = 0; j < jac.cols(); j++) jac.coeffRef(i, j) = av[i].getADValue(j);
+    }
+  }
+
+ protected:
+};
+
+//@}
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_ADOLC_FORWARD_MODULE_H
diff --git a/contrib/Eigen/AlignedVector3 b/contrib/Eigen/AlignedVector3
new file mode 100644
index 0000000..3be65a0
--- /dev/null
+++ b/contrib/Eigen/AlignedVector3
@@ -0,0 +1,212 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
+//
+// 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
+
+#ifndef EIGEN_ALIGNED_VECTOR3_MODULE_H
+#define EIGEN_ALIGNED_VECTOR3_MODULE_H
+
+#include "../../Eigen/Geometry"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/**
+ * \defgroup AlignedVector3_Module Aligned vector3 module
+ *
+ * \code
+ * #include <contrib/Eigen/AlignedVector3>
+ * \endcode
+ */
+//@{
+
+/** \class AlignedVector3
+ *
+ * \brief A vectorization friendly 3D vector
+ *
+ * This class represents a 3D vector internally using a 4D vector
+ * such that vectorization can be seamlessly enabled. Of course,
+ * the same result can be achieved by directly using a 4D vector.
+ * This class makes this process simpler.
+ *
+ */
+// TODO: Specialize Cwise.
+template <typename Scalar_>
+class AlignedVector3;
+
+namespace internal {
+template <typename Scalar_>
+struct traits<AlignedVector3<Scalar_> > : traits<Matrix<Scalar_, 3, 1, 0, 4, 1> > {};
+}  // namespace internal
+
+template <typename Scalar_>
+class AlignedVector3 : public MatrixBase<AlignedVector3<Scalar_> > {
+  typedef Matrix<Scalar_, 4, 1> CoeffType;
+  CoeffType m_coeffs;
+
+ public:
+  typedef MatrixBase<AlignedVector3<Scalar_> > Base;
+  EIGEN_DENSE_PUBLIC_INTERFACE(AlignedVector3)
+  using Base::operator*;
+
+  inline Index rows() const { return 3; }
+  inline Index cols() const { return 1; }
+
+  Scalar* data() { return m_coeffs.data(); }
+  const Scalar* data() const { return m_coeffs.data(); }
+  Index innerStride() const { return 1; }
+  Index outerStride() const { return 3; }
+
+  inline const Scalar& coeff(Index row, Index col) const { return m_coeffs.coeff(row, col); }
+
+  inline Scalar& coeffRef(Index row, Index col) { return m_coeffs.coeffRef(row, col); }
+
+  inline const Scalar& coeff(Index index) const { return m_coeffs.coeff(index); }
+
+  inline Scalar& coeffRef(Index index) { return m_coeffs.coeffRef(index); }
+
+  inline AlignedVector3() {}
+
+  inline AlignedVector3(const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, Scalar(0)) {}
+
+  inline AlignedVector3(const AlignedVector3& other) : Base(), m_coeffs(other.m_coeffs) {}
+
+  template <typename XprType, int Size = XprType::SizeAtCompileTime>
+  struct generic_assign_selector {};
+
+  template <typename XprType>
+  struct generic_assign_selector<XprType, 4> {
+    inline static void run(AlignedVector3& dest, const XprType& src) { dest.m_coeffs = src; }
+  };
+
+  template <typename XprType>
+  struct generic_assign_selector<XprType, 3> {
+    inline static void run(AlignedVector3& dest, const XprType& src) {
+      dest.m_coeffs.template head<3>() = src;
+      dest.m_coeffs.w() = Scalar(0);
+    }
+  };
+
+  template <typename Derived>
+  inline AlignedVector3(const MatrixBase<Derived>& other) {
+    generic_assign_selector<Derived>::run(*this, other.derived());
+  }
+
+  inline AlignedVector3& operator=(const AlignedVector3& other) {
+    m_coeffs = other.m_coeffs;
+    return *this;
+  }
+
+  template <typename Derived>
+  inline AlignedVector3& operator=(const MatrixBase<Derived>& other) {
+    generic_assign_selector<Derived>::run(*this, other.derived());
+    return *this;
+  }
+
+  inline AlignedVector3 operator+(const AlignedVector3& other) const {
+    return AlignedVector3(m_coeffs + other.m_coeffs);
+  }
+
+  inline AlignedVector3& operator+=(const AlignedVector3& other) {
+    m_coeffs += other.m_coeffs;
+    return *this;
+  }
+
+  inline AlignedVector3 operator-(const AlignedVector3& other) const {
+    return AlignedVector3(m_coeffs - other.m_coeffs);
+  }
+
+  inline AlignedVector3 operator-() const { return AlignedVector3(-m_coeffs); }
+
+  inline AlignedVector3& operator-=(const AlignedVector3& other) {
+    m_coeffs -= other.m_coeffs;
+    return *this;
+  }
+
+  inline AlignedVector3 operator*(const Scalar& s) const { return AlignedVector3(m_coeffs * s); }
+
+  inline friend AlignedVector3 operator*(const Scalar& s, const AlignedVector3& vec) {
+    return AlignedVector3(s * vec.m_coeffs);
+  }
+
+  inline AlignedVector3& operator*=(const Scalar& s) {
+    m_coeffs *= s;
+    return *this;
+  }
+
+  inline AlignedVector3 operator/(const Scalar& s) const { return AlignedVector3(m_coeffs / s); }
+
+  inline AlignedVector3& operator/=(const Scalar& s) {
+    m_coeffs /= s;
+    return *this;
+  }
+
+  inline Scalar dot(const AlignedVector3& other) const {
+    eigen_assert(m_coeffs.w() == Scalar(0));
+    eigen_assert(other.m_coeffs.w() == Scalar(0));
+    return m_coeffs.dot(other.m_coeffs);
+  }
+
+  inline void normalize() { m_coeffs /= norm(); }
+
+  inline AlignedVector3 normalized() const { return AlignedVector3(m_coeffs / norm()); }
+
+  inline Scalar sum() const {
+    eigen_assert(m_coeffs.w() == Scalar(0));
+    return m_coeffs.sum();
+  }
+
+  inline Scalar squaredNorm() const {
+    eigen_assert(m_coeffs.w() == Scalar(0));
+    return m_coeffs.squaredNorm();
+  }
+
+  inline Scalar norm() const {
+    using std::sqrt;
+    return sqrt(squaredNorm());
+  }
+
+  inline AlignedVector3 cross(const AlignedVector3& other) const {
+    return AlignedVector3(m_coeffs.cross3(other.m_coeffs));
+  }
+
+  template <typename Derived>
+  inline bool isApprox(const MatrixBase<Derived>& other,
+                       const RealScalar& eps = NumTraits<Scalar>::dummy_precision()) const {
+    return m_coeffs.template head<3>().isApprox(other, eps);
+  }
+
+  CoeffType& coeffs() { return m_coeffs; }
+  const CoeffType& coeffs() const { return m_coeffs; }
+};
+
+namespace internal {
+
+template <typename Scalar_>
+struct eval<AlignedVector3<Scalar_>, Dense> {
+  typedef const AlignedVector3<Scalar_>& type;
+};
+
+template <typename Scalar>
+struct evaluator<AlignedVector3<Scalar> > : evaluator<Matrix<Scalar, 4, 1> > {
+  typedef AlignedVector3<Scalar> XprType;
+  typedef evaluator<Matrix<Scalar, 4, 1> > Base;
+
+  evaluator(const XprType& m) : Base(m.coeffs()) {}
+};
+
+}  // namespace internal
+
+//@}
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_ALIGNED_VECTOR3_MODULE_H
diff --git a/contrib/Eigen/ArpackSupport b/contrib/Eigen/ArpackSupport
new file mode 100644
index 0000000..ba981d2
--- /dev/null
+++ b/contrib/Eigen/ArpackSupport
@@ -0,0 +1,35 @@
+// 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
+
+#ifndef EIGEN_ARPACKSUPPORT_MODULE_H
+#define EIGEN_ARPACKSUPPORT_MODULE_H
+
+#include "../../Eigen/Core"
+
+/** \defgroup ArpackSupport_Module Arpack support module
+ *
+ * This module provides a wrapper to Arpack, a library for sparse eigenvalue decomposition.
+ *
+ * \code
+ * #include <contrib/Eigen/ArpackSupport>
+ * \endcode
+ */
+
+#include "../../Eigen/SparseCholesky"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/ArpackSupport/ArpackSelfAdjointEigenSolver.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_ARPACKSUPPORT_MODULE_H
diff --git a/contrib/Eigen/AutoDiff b/contrib/Eigen/AutoDiff
new file mode 100644
index 0000000..03fe928
--- /dev/null
+++ b/contrib/Eigen/AutoDiff
@@ -0,0 +1,50 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// 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
+
+#ifndef EIGEN_AUTODIFF_MODULE_H
+#define EIGEN_AUTODIFF_MODULE_H
+
+#include "../../Eigen/Core"
+
+namespace Eigen {
+
+/**
+ * \defgroup AutoDiff_Module Auto Diff module
+ *
+ * This module features forward automatic differentiation via a simple
+ * templated scalar type wrapper AutoDiffScalar.
+ *
+ * Warning : this should NOT be confused with numerical differentiation, which
+ * is a different method and has its own module in Eigen : \ref NumericalDiff_Module.
+ *
+ * \code
+ * #include <contrib/Eigen/AutoDiff>
+ * \endcode
+ *
+ * See \ref AutoDiffExamples for introductory examples.
+ */
+//@{
+
+}  // namespace Eigen
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/AutoDiff/CoherentPadOp.h"
+#include "src/AutoDiff/AutoDiffScalar.h"
+#include "src/AutoDiff/AutoDiffJacobian.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+namespace Eigen {
+//@}
+}
+
+#endif  // EIGEN_AUTODIFF_MODULE_H
diff --git a/contrib/Eigen/BVH b/contrib/Eigen/BVH
new file mode 100644
index 0000000..85c8f5e
--- /dev/null
+++ b/contrib/Eigen/BVH
@@ -0,0 +1,113 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu>
+//
+// 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
+
+#ifndef EIGEN_BVH_MODULE_H
+#define EIGEN_BVH_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/Geometry"
+#include "../../Eigen/StdVector"
+#include <algorithm>
+#include <queue>
+
+namespace Eigen {
+
+/**
+  * \defgroup BVH_Module BVH module
+  * \brief This module provides generic bounding volume hierarchy algorithms
+  * and reference tree implementations.
+  *
+  *
+  * \code
+  * #include <contrib/Eigen/BVH>
+  * \endcode
+  *
+  * A bounding volume hierarchy (BVH) can accelerate many geometric queries.  This module provides a generic
+  implementation
+  * of the two basic algorithms over a BVH: intersection of a query object against all objects in the hierarchy and
+  minimization
+  * of a function over the objects in the hierarchy.  It also provides intersection and minimization over a cartesian
+  product of
+  * two BVH's.  A BVH accelerates intersection by using the fact that if a query object does not intersect a volume,
+  then it cannot
+  * intersect any object contained in that volume.  Similarly, a BVH accelerates minimization because the minimum of a
+  function
+  * over a volume is no greater than the minimum of a function over any object contained in it.
+  *
+  * Some sample queries that can be written in terms of intersection are:
+  *   - Determine all points where a ray intersects a triangle mesh
+  *   - Given a set of points, determine which are contained in a query sphere
+  *   - Given a set of spheres, determine which contain the query point
+  *   - Given a set of disks, determine if any is completely contained in a query rectangle (represent each 2D disk as a
+  point \f$(x,y,r)\f$
+  *     in 3D and represent the rectangle as a pyramid based on the original rectangle and shrinking in the \f$r\f$
+  direction)
+  *   - Given a set of points, count how many pairs are \f$d\pm\epsilon\f$ apart (done by looking at the cartesian
+  product of the set
+  *     of points with itself)
+  *
+  * Some sample queries that can be written in terms of function minimization over a set of objects are:
+  *   - Find the intersection between a ray and a triangle mesh closest to the ray origin (function is infinite off the
+  ray)
+  *   - Given a polyline and a query point, determine the closest point on the polyline to the query
+  *   - Find the diameter of a point cloud (done by looking at the cartesian product and using negative distance as the
+  function)
+  *   - Determine how far two meshes are from colliding (this is also a cartesian product query)
+  *
+  * This implementation decouples the basic algorithms both from the type of hierarchy (and the types of the bounding
+  volumes) and
+  * from the particulars of the query.  To enable abstraction from the BVH, the BVH is required to implement a generic
+  mechanism
+  * for traversal.  To abstract from the query, the query is responsible for keeping track of results.
+  *
+  * To be used in the algorithms, a hierarchy must implement the following traversal mechanism (see KdBVH for a sample
+  implementation): \code typedef Volume  //the type of bounding volume typedef Object  //the type of object in the
+  hierarchy typedef Index   //a reference to a node in the hierarchy--typically an int or a pointer typedef
+  VolumeIterator //an iterator type over node children--returns Index typedef ObjectIterator //an iterator over object
+  (leaf) children--returns const Object & Index getRootIndex() const //returns the index of the hierarchy root const
+  Volume &getVolume(Index index) const //returns the bounding volume of the node at given index void getChildren(Index
+  index, VolumeIterator &outVBegin, VolumeIterator &outVEnd, ObjectIterator &outOBegin, ObjectIterator &outOEnd) const
+      //getChildren takes a node index and makes [outVBegin, outVEnd) range over its node children
+      //and [outOBegin, outOEnd) range over its object children
+    \endcode
+  *
+  * To use the hierarchy, call BVIntersect or BVMinimize, passing it a BVH (or two, for cartesian product) and a
+  minimizer or intersector.
+  * For an intersection query on a single BVH, the intersector encapsulates the query and must provide two functions:
+  * \code
+      bool intersectVolume(const Volume &volume) //returns true if the query intersects the volume
+      bool intersectObject(const Object &object) //returns true if the intersection search should terminate immediately
+    \endcode
+  * The guarantee that BVIntersect provides is that intersectObject will be called on every object whose bounding volume
+  * intersects the query (but possibly on other objects too) unless the search is terminated prematurely.  It is the
+  * responsibility of the intersectObject function to keep track of the results in whatever manner is appropriate.
+  * The cartesian product intersection and the BVMinimize queries are similar--see their individual documentation.
+  *
+  * The following is a simple but complete example for how to use the BVH to accelerate the search for a closest
+  red-blue point pair:
+  * \include BVH_Example.cpp
+  * Output: \verbinclude BVH_Example.out
+  */
+}
+
+//@{
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/BVH/BVAlgorithms.h"
+#include "src/BVH/KdBVH.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+//@}
+
+#endif  // EIGEN_BVH_MODULE_H
diff --git a/contrib/Eigen/CMakeLists.txt b/contrib/Eigen/CMakeLists.txt
new file mode 100644
index 0000000..ecf39bc
--- /dev/null
+++ b/contrib/Eigen/CMakeLists.txt
@@ -0,0 +1,42 @@
+# SPDX-FileCopyrightText: The Eigen Authors
+# SPDX-License-Identifier: MPL-2.0
+
+# When adding a new umbrella header here, also add a corresponding
+# forwarding shim under unsupported/Eigen/ (and update the
+# Eigen_LegacyShim_HEADERS list in unsupported/Eigen/CMakeLists.txt) so
+# the legacy <unsupported/Eigen/...> include path keeps working.
+set(Eigen_HEADERS
+  AdolcForward
+  AlignedVector3
+  ArpackSupport
+  AutoDiff
+  BVH
+  EulerAngles
+  FFT
+  GPU
+  IterativeSolvers
+  KroneckerProduct
+  LevenbergMarquardt
+  MatrixFunctions
+  MPRealSupport
+  NNLS
+  NonLinearOptimization
+  NumericalDiff
+  OpenGLSupport
+  Polynomials
+  SparseExtra
+  SpecialFunctions
+  Splines
+  StructuredMatrices
+  Tensor
+  TensorSymmetry
+  )
+
+if(EIGEN_INSTALL)
+  install(FILES
+    ${Eigen_HEADERS}
+    DESTINATION ${INCLUDE_INSTALL_DIR}/contrib/Eigen COMPONENT Devel
+    )
+
+  install(DIRECTORY src DESTINATION ${INCLUDE_INSTALL_DIR}/contrib/Eigen COMPONENT Devel FILES_MATCHING PATTERN "*.h")
+endif()
diff --git a/contrib/Eigen/EulerAngles b/contrib/Eigen/EulerAngles
new file mode 100644
index 0000000..64aa3c2
--- /dev/null
+++ b/contrib/Eigen/EulerAngles
@@ -0,0 +1,45 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2015 Tal Hadad <tal_hd@hotmail.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
+
+#ifndef EIGEN_EULERANGLES_MODULE_H
+#define EIGEN_EULERANGLES_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/Geometry"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/**
+ * \defgroup EulerAngles_Module EulerAngles module
+ * \brief This module provides generic euler angles rotation.
+ *
+ * Euler angles are a way to represent 3D rotation.
+ *
+ * In order to use this module in your code, include this header:
+ * \code
+ * #include <contrib/Eigen/EulerAngles>
+ * \endcode
+ *
+ * See \ref EulerAngles for more information.
+ *
+ */
+
+}
+
+// IWYU pragma: begin_exports
+#include "src/EulerAngles/EulerSystem.h"
+#include "src/EulerAngles/EulerAngles.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_EULERANGLES_MODULE_H
diff --git a/contrib/Eigen/FFT b/contrib/Eigen/FFT
new file mode 100644
index 0000000..56addd9
--- /dev/null
+++ b/contrib/Eigen/FFT
@@ -0,0 +1,494 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Mark Borgerding mark a borgerding net
+//
+// 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
+
+#ifndef EIGEN_FFT_MODULE_H
+#define EIGEN_FFT_MODULE_H
+
+#include <complex>
+#include <vector>
+#include <map>
+#include "../../Eigen/Core"
+
+/**
+ * \defgroup FFT_Module Fast Fourier Transform module
+ *
+ * \code
+ * #include <contrib/Eigen/FFT>
+ * \endcode
+ *
+ * This module provides Fast Fourier transformation, with a configurable backend
+ * implementation.
+ *
+ * The default implementation is based on kissfft. It is a small, free, and
+ * reasonably efficient default.
+ *
+ * There are currently four implementation backend:
+ *
+ * - kissfft(https://github.com/mborgerding/kissfft) : Simple and not so fast, BSD-3-Clause.
+ *   It is a mixed-radix Fast Fourier Transform based up on the principle, "Keep It Simple, Stupid."
+ *   Notice that:kissfft fails to handle "atypically-sized" inputs(i.e., sizes with large factors),a workaround is using
+ * fftw or pocketfft.
+ * - fftw (http://www.fftw.org) : faster, GPL -- incompatible with Eigen in LGPL form, bigger code size.
+ * - MKL (https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl-download.html) : fastest, free -- may be
+ * incompatible with Eigen in GPL form.
+ * - PocketFFT/DUCC (https://gitlab.mpcdf.mpg.de/mtr/pocketfft, https://gitlab.mpcdf.mpg.de/mtr/ducc) : faster than
+ *   kissfft, BSD 3-clause. A heavily modified implementation of FFTPack with the following advantages:
+ *   -# strictly C++14 compliant
+ *   -# more accurate twiddle factor computation
+ *   -# very fast plan generation
+ *   -# worst case complexity for transform sizes with large prime factors is N*log(N),
+ *      because Bluestein's algorithm is used for these cases.
+ *   .
+ *   According to the author, DUCC contains the "evolution" of pocketfft, though the interface is very similar.
+ *
+ * \section FFTThreadSafety Thread safety
+ *
+ * An FFT object is not thread-safe: it caches a plan, so concurrent transforms need one object per
+ * thread. Distinct objects may be used concurrently.
+ *
+ * That is not by itself enough for the FFTW backend, whose planner keeps process-wide state and
+ * whose only concurrent entry points are \c fftw_execute and its new-array variants. %Eigen
+ * therefore serializes plan creation and destruction on a mutex of its own, which covers every
+ * planner call %Eigen makes from within one process image.
+ *
+ * Two cases fall outside that. FFTW planner calls made directly, not through %Eigen, share nothing
+ * with %Eigen's mutex. And a program that loads several shared libraries which each carry their own
+ * copy of %Eigen may end up with one mutex per library instead of one per process: %Eigen gives the
+ * mutex default visibility so that the dynamic linker collapses those copies, which covers ELF
+ * libraries linked normally or loaded with \c RTLD_GLOBAL, but not separate Windows DLLs, and not a
+ * library loaded with \c RTLD_LOCAL unless the compiler emitted a unique symbol for the definition.
+ * In either case, call FFTW's own \c fftw_make_planner_thread_safe() once before any transform: it
+ * puts the lock inside the planner, where it applies to every caller. It needs FFTW 3.3.5 or later,
+ * built with thread support.
+ *
+ * \section FFTDesign Design
+ *
+ * The following design decisions were made concerning scaling and
+ * half-spectrum for real FFT.
+ *
+ * The intent is to facilitate generic programming and ease migrating code
+ * from  Matlab/octave.
+ * We think the default behavior of Eigen/FFT should favor correctness and
+ * generality over speed. Of course, the caller should be able to "opt-out" from this
+ * behavior and get the speed increase if they want it.
+ *
+ * 1) %Scaling:
+ * Other libraries (FFTW,IMKL,KISSFFT)  do not perform scaling, so there
+ * is a constant gain incurred after the forward&inverse transforms , so
+ * IFFT(FFT(x)) = Kx;  this is done to avoid a vector-by-value multiply.
+ * The downside is that algorithms that worked correctly in Matlab/octave
+ * don't behave the same way once implemented in C++.
+ *
+ * How Eigen/FFT differs: invertible scaling is performed so IFFT( FFT(x) ) = x.
+ *
+ * 2) Real FFT half-spectrum
+ * Other libraries use only half the frequency spectrum (plus one extra
+ * sample for the Nyquist bin) for a real FFT, the other half is the
+ * conjugate-symmetric of the first half.  This saves them a copy and some
+ * memory.  The downside is the caller needs to have special logic for the
+ * number of bins in complex vs real.
+ *
+ * How Eigen/FFT differs: The full spectrum is returned from the forward
+ * transform.  This facilitates generic template programming by obviating
+ * separate specializations for real vs complex.  On the inverse
+ * transform, only half the spectrum is actually used if the output type is real.
+ */
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+
+#ifdef EIGEN_FFTW_DEFAULT
+// FFTW: faster, GPL -- incompatible with Eigen in LGPL form, bigger code size
+#include <fftw3.h>
+#include "src/FFT/fftw_impl.h"
+namespace Eigen {
+template <typename T>
+struct default_fft_impl : public internal::fftw_impl<T> {};
+}  // namespace Eigen
+#elif defined EIGEN_MKL_DEFAULT
+// intel Math Kernel Library: fastest, free -- may be incompatible with Eigen in GPL form
+#include "src/FFT/imklfft_impl.h"
+namespace Eigen {
+template <typename T>
+struct default_fft_impl : public internal::imklfft::imklfft_impl<T> {};
+}  // namespace Eigen
+#elif defined EIGEN_POCKETFFT_DEFAULT
+// internal::pocketfft_impl: a heavily modified implementation of FFTPack, with many advantages.
+#include <pocketfft_hdronly.h>
+#include "src/FFT/pocketfft_impl.h"
+namespace Eigen {
+template <typename T>
+struct default_fft_impl : public internal::pocketfft_impl<T> {};
+}  // namespace Eigen
+#elif defined EIGEN_DUCCFFT_DEFAULT
+#include <ducc0/fft/fft.h>
+#include <ducc0/infra/string_utils.h>
+#include <ducc0/fft/fftnd_impl.h>
+#include "src/FFT/duccfft_impl.h"
+namespace Eigen {
+template <typename T>
+struct default_fft_impl : public internal::duccfft_impl<T> {};
+}  // namespace Eigen
+#else
+// internal::kissfft_impl:  small, free, reasonably efficient default, derived from kissfft
+#include "src/FFT/kissfft_impl.h"
+namespace Eigen {
+template <typename T>
+struct default_fft_impl : public internal::kissfft_impl<T> {};
+}  // namespace Eigen
+#endif
+
+// IWYU pragma: end_exports
+
+namespace Eigen {
+
+//
+template <typename T_SrcMat, typename T_FftIfc>
+struct fft_fwd_proxy;
+template <typename T_SrcMat, typename T_FftIfc>
+struct fft_inv_proxy;
+
+namespace internal {
+template <typename T_SrcMat, typename T_FftIfc>
+struct traits<fft_fwd_proxy<T_SrcMat, T_FftIfc> > {
+  typedef typename T_SrcMat::PlainObject ReturnType;
+};
+template <typename T_SrcMat, typename T_FftIfc>
+struct traits<fft_inv_proxy<T_SrcMat, T_FftIfc> > {
+  typedef typename T_SrcMat::PlainObject ReturnType;
+};
+}  // namespace internal
+
+template <typename T_SrcMat, typename T_FftIfc>
+struct fft_fwd_proxy : public ReturnByValue<fft_fwd_proxy<T_SrcMat, T_FftIfc> > {
+  typedef Eigen::Index Index;
+
+  fft_fwd_proxy(const T_SrcMat& src, T_FftIfc& fft, Index nfft) : m_src(src), m_ifc(fft), m_nfft(nfft) {}
+
+  template <typename T_DestMat>
+  void evalTo(T_DestMat& dst) const;
+
+  Index rows() const { return m_src.rows(); }
+  Index cols() const { return m_src.cols(); }
+
+ protected:
+  const T_SrcMat& m_src;
+  T_FftIfc& m_ifc;
+  Index m_nfft;
+};
+
+template <typename T_SrcMat, typename T_FftIfc>
+struct fft_inv_proxy : public ReturnByValue<fft_inv_proxy<T_SrcMat, T_FftIfc> > {
+  typedef Eigen::Index Index;
+
+  fft_inv_proxy(const T_SrcMat& src, T_FftIfc& fft, Index nfft) : m_src(src), m_ifc(fft), m_nfft(nfft) {}
+
+  template <typename T_DestMat>
+  void evalTo(T_DestMat& dst) const;
+
+  Index rows() const { return m_src.rows(); }
+  Index cols() const { return m_src.cols(); }
+
+ protected:
+  const T_SrcMat& m_src;
+  T_FftIfc& m_ifc;
+  Index m_nfft;
+};
+
+namespace internal {
+
+// The transforms are one-dimensional, but a matrix with a dynamic dimension only knows at run
+// time whether that dimension is one, so it cannot be rejected at compile time the way a matrix
+// of known two-dimensional shape can. Only the latter is excluded here.
+template <typename Derived>
+struct fft_accepts_as_vector {
+  static constexpr bool value = bool(Derived::IsVectorAtCompileTime) || int(Derived::RowsAtCompileTime) == Dynamic ||
+                                int(Derived::ColsAtCompileTime) == Dynamic;
+};
+
+// Distance between consecutive elements of a one-dimensional operand. The inner stride does not
+// answer this once matrices are accepted: a matrix holding a single row steps along its outer
+// stride, and only a unit distance lets the transform run over the operand's own memory.
+template <typename Derived>
+EIGEN_STRONG_INLINE Index fft_linear_stride(const DenseBase<Derived>& x) {
+  return x.rows() == 1 ? x.derived().colStride() : x.derived().rowStride();
+}
+
+// Resize a one-dimensional destination. Every orientation a compile-time dimension leaves open
+// is settled here: a fixed dimension other than one can only be the long one, and a destination
+// with two dynamic dimensions takes the orientation of the source.
+template <typename Derived>
+EIGEN_STRONG_INLINE void fft_resize_as_vector(DenseBase<Derived>& dst, Index size, bool source_is_row) {
+  // A destination already holding the transform's length in one dimension keeps that shape, which
+  // is the only one a view such as a Map can be given at all.
+  if ((dst.rows() == 1 && dst.cols() == size) || (dst.cols() == 1 && dst.rows() == size)) return;
+
+  constexpr int Rows = int(Derived::RowsAtCompileTime);
+  constexpr int Cols = int(Derived::ColsAtCompileTime);
+  const bool row = Rows == 1         ? true
+                   : Cols == 1       ? false
+                   : Cols != Dynamic ? true
+                   : Rows != Dynamic ? false
+                                     : source_is_row;
+  dst.derived().resize(row ? 1 : size, row ? size : 1);
+}
+
+}  // namespace internal
+
+#define EIGEN_STATIC_ASSERT_FFT_VECTOR(TYPE) \
+  EIGEN_STATIC_ASSERT(internal::fft_accepts_as_vector<TYPE>::value, YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX)
+
+template <typename T_Scalar, typename T_Impl = default_fft_impl<T_Scalar> >
+class FFT {
+ public:
+  typedef T_Impl impl_type;
+  typedef Eigen::Index Index;
+  typedef typename impl_type::Scalar Scalar;
+  typedef typename impl_type::Complex Complex;
+
+  using Flag = int;
+  static constexpr Flag Default = 0;
+  static constexpr Flag Unscaled = 1;
+  static constexpr Flag HalfSpectrum = 2;
+  static constexpr Flag Speedy = 32767;
+
+  FFT(const impl_type& impl = impl_type(), Flag flags = Default) : m_impl(impl), m_flag(flags) {
+    eigen_assert((flags == Default || flags == Unscaled || flags == HalfSpectrum || flags == Speedy) &&
+                 "invalid flags argument");
+  }
+
+  inline bool HasFlag(Flag f) const { return (m_flag & (int)f) == f; }
+
+  inline void SetFlag(Flag f) { m_flag |= (int)f; }
+
+  inline void ClearFlag(Flag f) { m_flag &= (~(int)f); }
+
+  inline void fwd(Complex* dst, const Scalar* src, Index nfft) {
+    m_impl.fwd(dst, src, static_cast<int>(nfft));
+    if (HasFlag(HalfSpectrum) == false) ReflectSpectrum(dst, nfft);
+  }
+
+  inline void fwd(Complex* dst, const Complex* src, Index nfft) { m_impl.fwd(dst, src, static_cast<int>(nfft)); }
+
+#if defined EIGEN_FFTW_DEFAULT || defined EIGEN_POCKETFFT_DEFAULT || defined EIGEN_DUCCFFT_DEFAULT || \
+    defined EIGEN_MKL_DEFAULT
+  inline void fwd2(Complex* dst, const Complex* src, int n0, int n1) { m_impl.fwd2(dst, src, n0, n1); }
+#endif
+
+  template <typename Input_>
+  inline void fwd(std::vector<Complex>& dst, const std::vector<Input_>& src) {
+    EIGEN_IF_CONSTEXPR (NumTraits<Input_>::IsComplex == 0) {
+      if (HasFlag(HalfSpectrum))
+        dst.resize((src.size() >> 1) + 1);  // half the bins + Nyquist bin
+      else
+        dst.resize(src.size());
+    } else {
+      dst.resize(src.size());
+    }
+    fwd(&dst[0], &src[0], src.size());
+  }
+
+  template <typename InputDerived, typename ComplexDerived>
+  inline void fwd(DenseBase<ComplexDerived>& dst, const DenseBase<InputDerived>& src, Index nfft = -1) {
+    typedef typename ComplexDerived::Scalar dst_type;
+    typedef typename InputDerived::Scalar src_type;
+    EIGEN_STATIC_ASSERT_FFT_VECTOR(InputDerived)
+    EIGEN_STATIC_ASSERT_FFT_VECTOR(ComplexDerived)
+    EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived, InputDerived)  // size at compile-time
+    EIGEN_STATIC_ASSERT(
+        (std::is_same<dst_type, Complex>::value),
+        YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+    EIGEN_STATIC_ASSERT(int(InputDerived::Flags) & int(ComplexDerived::Flags) & DirectAccessBit,
+                        THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
+    eigen_assert((src.rows() == 1 || src.cols() == 1) && "the input of an FFT must be one-dimensional");
+
+    if (nfft < 1) nfft = src.size();
+
+    Index dst_size = nfft;
+    EIGEN_IF_CONSTEXPR (NumTraits<src_type>::IsComplex == 0) {
+      if (HasFlag(HalfSpectrum)) {
+        dst_size = (nfft >> 1) + 1;
+      }
+    }
+    internal::fft_resize_as_vector(dst, dst_size, src.rows() == 1);
+
+    if (internal::fft_linear_stride(src) != 1 || src.size() < nfft) {
+      Matrix<src_type, 1, Dynamic> tmp(1, nfft);
+      const Index copy_size = (std::min)(src.size(), nfft);
+      if (copy_size > 0) {
+        tmp.head(copy_size) = src.reshaped().head(copy_size);
+      }
+      if (copy_size < nfft) tmp.tail(nfft - copy_size).setZero();
+      if (internal::fft_linear_stride(dst) != 1) {
+        Matrix<dst_type, 1, Dynamic> out(1, dst_size);
+        fwd(out.data(), tmp.data(), nfft);
+        dst.derived() = out.reshaped(dst.rows(), dst.cols());
+      } else {
+        fwd(dst.derived().data(), tmp.data(), nfft);
+      }
+    } else {
+      if (internal::fft_linear_stride(dst) != 1) {
+        Matrix<dst_type, 1, Dynamic> out(1, dst_size);
+        fwd(out.data(), src.derived().data(), nfft);
+        dst.derived() = out.reshaped(dst.rows(), dst.cols());
+      } else {
+        fwd(dst.derived().data(), src.derived().data(), nfft);
+      }
+    }
+  }
+
+  template <typename InputDerived>
+  inline fft_fwd_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> > fwd(const DenseBase<InputDerived>& src,
+                                                                            Index nfft = -1) {
+    return fft_fwd_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> >(src, *this, nfft);
+  }
+
+  template <typename InputDerived>
+  inline fft_inv_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> > inv(const DenseBase<InputDerived>& src,
+                                                                            Index nfft = -1) {
+    return fft_inv_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> >(src, *this, nfft);
+  }
+
+  inline void inv(Complex* dst, const Complex* src, Index nfft) {
+    m_impl.inv(dst, src, static_cast<int>(nfft));
+    if (HasFlag(Unscaled) == false) scale(dst, Scalar(1. / nfft), nfft);  // scale the time series
+  }
+
+  inline void inv(Scalar* dst, const Complex* src, Index nfft) {
+    m_impl.inv(dst, src, static_cast<int>(nfft));
+    if (HasFlag(Unscaled) == false) scale(dst, Scalar(1. / nfft), nfft);  // scale the time series
+  }
+
+  template <typename OutputDerived, typename ComplexDerived>
+  inline void inv(DenseBase<OutputDerived>& dst, const DenseBase<ComplexDerived>& src, Index nfft = -1) {
+    typedef typename ComplexDerived::Scalar src_type;
+    typedef typename ComplexDerived::RealScalar real_type;
+    typedef typename OutputDerived::Scalar dst_type;
+    const bool realfft = (NumTraits<dst_type>::IsComplex == 0);
+    EIGEN_STATIC_ASSERT_FFT_VECTOR(OutputDerived)
+    EIGEN_STATIC_ASSERT_FFT_VECTOR(ComplexDerived)
+    EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived, OutputDerived)  // size at compile-time
+    EIGEN_STATIC_ASSERT(
+        (std::is_same<src_type, Complex>::value),
+        YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+    EIGEN_STATIC_ASSERT(int(OutputDerived::Flags) & int(ComplexDerived::Flags) & DirectAccessBit,
+                        THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
+    eigen_assert((src.rows() == 1 || src.cols() == 1) && "the input of an FFT must be one-dimensional");
+
+    if (nfft < 1) {  // automatic FFT size determination
+      if (realfft && HasFlag(HalfSpectrum))
+        nfft = 2 * (src.size() - 1);  // assume even fft size
+      else
+        nfft = src.size();
+    }
+    internal::fft_resize_as_vector(dst, nfft, src.rows() == 1);
+
+    // check for nfft that does not fit the input data size
+    Index resize_input = (realfft && HasFlag(HalfSpectrum)) ? ((nfft / 2 + 1) - src.size()) : (nfft - src.size());
+
+    if (internal::fft_linear_stride(src) != 1 || resize_input) {
+      // if the vector is strided, then we need to copy it to a packed temporary
+      const auto src_lin = src.reshaped();
+      Matrix<src_type, 1, Dynamic> tmp;
+      if (resize_input) {
+        size_t ncopy = (std::min)(src.size(), src.size() + resize_input);
+        tmp.setZero(src.size() + resize_input);
+        if (realfft && HasFlag(HalfSpectrum)) {
+          // pad at the Nyquist bin
+          tmp.head(ncopy) = src_lin.head(ncopy);
+          tmp(ncopy - 1) = real(tmp(ncopy - 1));  // enforce real-only Nyquist bin
+        } else {
+          size_t nhead, ntail;
+          nhead = 1 + ncopy / 2 - 1;  // range  [0:pi)
+          ntail = ncopy / 2 - 1;      // range (-pi:0)
+          tmp.head(nhead) = src_lin.head(nhead);
+          tmp.tail(ntail) = src_lin.tail(ntail);
+          if (resize_input <
+              0) {  // shrinking -- create the Nyquist bin as the average of the two bins that fold into it
+            tmp(nhead) = (src_lin(nfft / 2) + src_lin(src.size() - nfft / 2)) * real_type(.5);
+          } else {  // expanding -- split the old Nyquist bin into two halves
+            tmp(nhead) = src_lin(nhead) * real_type(.5);
+            tmp(tmp.size() - nhead) = tmp(nhead);
+          }
+        }
+      } else {
+        tmp = src_lin;
+      }
+
+      if (internal::fft_linear_stride(dst) != 1) {
+        Matrix<dst_type, 1, Dynamic> out(1, nfft);
+        inv(out.data(), tmp.data(), nfft);
+        dst.derived() = out.reshaped(dst.rows(), dst.cols());
+      } else {
+        inv(dst.derived().data(), tmp.data(), nfft);
+      }
+    } else {
+      if (internal::fft_linear_stride(dst) != 1) {
+        Matrix<dst_type, 1, Dynamic> out(1, nfft);
+        inv(out.data(), src.derived().data(), nfft);
+        dst.derived() = out.reshaped(dst.rows(), dst.cols());
+      } else {
+        inv(dst.derived().data(), src.derived().data(), nfft);
+      }
+    }
+  }
+
+  template <typename Output_>
+  inline void inv(std::vector<Output_>& dst, const std::vector<Complex>& src, Index nfft = -1) {
+    if (nfft < 1)
+      nfft = (NumTraits<Output_>::IsComplex == 0 && HasFlag(HalfSpectrum)) ? 2 * (src.size() - 1) : src.size();
+    dst.resize(nfft);
+    inv(&dst[0], &src[0], nfft);
+  }
+
+#if defined EIGEN_FFTW_DEFAULT || defined EIGEN_POCKETFFT_DEFAULT || defined EIGEN_DUCCFFT_DEFAULT || \
+    defined EIGEN_MKL_DEFAULT
+  inline void inv2(Complex* dst, const Complex* src, int n0, int n1) {
+    m_impl.inv2(dst, src, n0, n1);
+    if (HasFlag(Unscaled) == false) scale(dst, Scalar(1) / (n0 * n1), n0 * n1);
+  }
+#endif
+
+  inline impl_type& impl() { return m_impl; }
+
+ private:
+  template <typename T_Data>
+  inline void scale(T_Data* x, Scalar s, Index nx) {
+    for (int k = 0; k < nx; ++k) *x++ *= s;
+  }
+
+  inline void ReflectSpectrum(Complex* freq, Index nfft) {
+    // create the implicit right-half spectrum (conjugate-mirror of the left-half)
+    Index nhbins = (nfft >> 1) + 1;
+    for (Index k = nhbins; k < nfft; ++k) freq[k] = conj(freq[nfft - k]);
+  }
+
+  impl_type m_impl;
+  int m_flag;
+};
+
+template <typename T_SrcMat, typename T_FftIfc>
+template <typename T_DestMat>
+inline void fft_fwd_proxy<T_SrcMat, T_FftIfc>::evalTo(T_DestMat& dst) const {
+  m_ifc.fwd(dst, m_src, m_nfft);
+}
+
+template <typename T_SrcMat, typename T_FftIfc>
+template <typename T_DestMat>
+inline void fft_inv_proxy<T_SrcMat, T_FftIfc>::evalTo(T_DestMat& dst) const {
+  m_ifc.inv(dst, m_src, m_nfft);
+}
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_FFT_MODULE_H
diff --git a/contrib/Eigen/GPU b/contrib/Eigen/GPU
new file mode 100644
index 0000000..9e55590
--- /dev/null
+++ b/contrib/Eigen/GPU
@@ -0,0 +1,79 @@
+// 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
+
+#ifndef EIGEN_GPU_MODULE_H
+#define EIGEN_GPU_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/SparseCore"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+/** \defgroup GPU_Module GPU module
+ *
+ * GPU-accelerated dense linear algebra using NVIDIA CUDA libraries
+ * (cuSOLVER and cuBLAS).
+ *
+ * This module provides explicit GPU solver classes that coexist with Eigen's
+ * CPU solvers. Unlike the LAPACKE dispatch (which replaces the CPU
+ * implementation globally), GPU classes are separate types the user
+ * instantiates by choice:
+ *
+ * \code
+ * #define EIGEN_USE_GPU
+ * #include <contrib/Eigen/GPU>
+ *
+ * // CPU path (unchanged)
+ * Eigen::LLT<Eigen::MatrixXd> llt_cpu(A);
+ *
+ * // GPU path (explicit)
+ * Eigen::gpu::LLT<double> llt_gpu(A);   // L stays on device
+ * auto X = llt_gpu.solve(B);            // only B transferred per solve
+ * \endcode
+ *
+ * Requires CUDA 11.4+.
+ */
+
+#ifdef EIGEN_USE_GPU
+// IWYU pragma: begin_exports
+#include "src/GPU/FwdDecl.h"
+#include "src/GPU/Meta.h"
+#include "src/GPU/type_traits.h"
+#include "src/GPU/DeviceScalar.h"
+#include "src/GPU/DeviceMatrix.h"
+#include "src/GPU/GpuContext.h"
+#include "src/GPU/DeviceExpr.h"
+#include "src/GPU/DeviceBlasExpr.h"
+#include "src/GPU/DeviceSolverExpr.h"
+#include "src/GPU/DeviceDispatch.h"
+#include "src/GPU/GpuSolverContext.h"
+#include "src/GPU/GpuLLT.h"
+#include "src/GPU/GpuLU.h"
+#include "src/GPU/GpuQR.h"
+#include "src/GPU/GpuSVD.h"
+#include "src/GPU/GpuEigenSolver.h"
+#include "src/GPU/CuFftSupport.h"
+#include "src/GPU/GpuFFT.h"
+#include "src/GPU/CuSparseSupport.h"
+#ifdef EIGEN_SPARSECORE_MODULE_H
+#include "src/GPU/GpuSparseContext.h"
+#endif
+#if defined(EIGEN_CUDSS) && defined(EIGEN_SPARSECORE_MODULE_H)
+#include "src/GPU/CuDssSupport.h"
+#include "src/GPU/GpuSparseSolverBase.h"
+#include "src/GPU/GpuSparseLLT.h"
+#include "src/GPU/GpuSparseLDLT.h"
+#include "src/GPU/GpuSparseLU.h"
+#endif
+// IWYU pragma: end_exports
+#endif
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_GPU_MODULE_H
diff --git a/contrib/Eigen/IterativeSolvers b/contrib/Eigen/IterativeSolvers
new file mode 100644
index 0000000..41bfdfc
--- /dev/null
+++ b/contrib/Eigen/IterativeSolvers
@@ -0,0 +1,25 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// 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
+
+#ifndef EIGEN_ITERATIVE_SOLVERS_MODULE_H
+#define EIGEN_ITERATIVE_SOLVERS_MODULE_H
+
+// The contents of this module have been promoted to the supported
+// Eigen/IterativeLinearSolvers module. This header is retained as a thin
+// forwarding shim for backwards compatibility and may be removed in a future
+// release. Please include <Eigen/IterativeLinearSolvers> directly instead.
+#ifndef EIGEN_NO_DEPRECATED_WARNING
+#pragma message( \
+    "unsupported/Eigen/IterativeSolvers is deprecated and forwards to <Eigen/IterativeLinearSolvers>; please include that header directly. Define EIGEN_NO_DEPRECATED_WARNING to silence this message.")
+#endif
+
+#include "../../Eigen/IterativeLinearSolvers"
+
+#endif  // EIGEN_ITERATIVE_SOLVERS_MODULE_H
diff --git a/contrib/Eigen/KroneckerProduct b/contrib/Eigen/KroneckerProduct
new file mode 100644
index 0000000..730284e
--- /dev/null
+++ b/contrib/Eigen/KroneckerProduct
@@ -0,0 +1,39 @@
+// 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
+
+#ifndef EIGEN_KRONECKER_PRODUCT_MODULE_H
+#define EIGEN_KRONECKER_PRODUCT_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/SparseCore"
+
+namespace Eigen {
+
+/**
+ * \defgroup KroneckerProduct_Module KroneckerProduct module
+ *
+ * This module contains an experimental Kronecker product implementation.
+ *
+ * \code
+ * #include <contrib/Eigen/KroneckerProduct>
+ * \endcode
+ */
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/KroneckerProduct/KroneckerTensorProduct.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_KRONECKER_PRODUCT_MODULE_H
diff --git a/contrib/Eigen/LevenbergMarquardt b/contrib/Eigen/LevenbergMarquardt
new file mode 100644
index 0000000..3f595e0
--- /dev/null
+++ b/contrib/Eigen/LevenbergMarquardt
@@ -0,0 +1,46 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+//
+// 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
+
+#ifndef EIGEN_LEVENBERGMARQUARDT_MODULE_H
+#define EIGEN_LEVENBERGMARQUARDT_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/Jacobi"
+#include "../../Eigen/QR"
+#include "../../Eigen/SparseCore"
+#include "../../Eigen/SparseQR"
+#include "NumericalDiff"
+
+/**
+ * \defgroup LevenbergMarquardt_Module Levenberg-Marquardt module
+ *
+ * \code
+ * #include <contrib/Eigen/LevenbergMarquardt>
+ * \endcode
+ *
+ *
+ */
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+#include "src/LevenbergMarquardt/LMqrsolv.h"
+#include "src/LevenbergMarquardt/LMcovar.h"
+#include "src/LevenbergMarquardt/LMpar.h"
+#endif
+
+#include "src/LevenbergMarquardt/LevenbergMarquardt.h"
+#include "src/LevenbergMarquardt/LMonestep.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_LEVENBERGMARQUARDT_MODULE_H
diff --git a/contrib/Eigen/MPRealSupport b/contrib/Eigen/MPRealSupport
new file mode 100644
index 0000000..756e89e
--- /dev/null
+++ b/contrib/Eigen/MPRealSupport
@@ -0,0 +1,219 @@
+// This file is part of a joint effort between Eigen, a lightweight C++ template library
+// for linear algebra, and MPFR C++, a C++ interface to MPFR library (http://www.holoborodko.com/pavel/)
+//
+// Copyright (C) 2010-2012 Pavel Holoborodko <pavel@holoborodko.com>
+// Copyright (C) 2010 Konstantin Holoborodko <konstantin@holoborodko.com>
+// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// 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
+
+#ifndef EIGEN_MPREALSUPPORT_MODULE_H
+#define EIGEN_MPREALSUPPORT_MODULE_H
+
+#include "../../Eigen/Core"
+#include <mpreal.h>
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/**
+  * \defgroup MPRealSupport_Module MPFRC++ Support module
+  * \code
+  * #include <contrib/Eigen/MPRealSupport>
+  * \endcode
+  *
+  * This module provides support for multi precision floating point numbers
+  * via the <a href="http://www.holoborodko.com/pavel/mpfr">MPFR C++</a>
+  * library which itself is built upon <a href="http://www.mpfr.org/">MPFR</a>/<a href="http://gmplib.org/">GMP</a>.
+  *
+  * \warning MPFR C++ is licensed under the GPL.
+  *
+  * You can find a copy of MPFR C++ that is known to be compatible in the contrib/test/mpreal folder.
+  *
+  * Here is an example:
+  *
+\code
+#include <iostream>
+#include <contrib/Eigen/MPRealSupport>
+#include <Eigen/LU>
+using namespace mpfr;
+using namespace Eigen;
+int main()
+{
+  // set precision to 256 bits (double has only 53 bits)
+  mpreal::set_default_prec(256);
+  // Declare matrix and vector types with multi-precision scalar type
+  typedef Matrix<mpreal,Dynamic,Dynamic>  MatrixXmp;
+  typedef Matrix<mpreal,Dynamic,1>        VectorXmp;
+
+  MatrixXmp A = MatrixXmp::Random(100,100);
+  VectorXmp b = VectorXmp::Random(100);
+
+  // Solve Ax=b using LU
+  VectorXmp x = A.lu().solve(b);
+  std::cout << "relative error: " << (A*x - b).norm() / b.norm() << std::endl;
+  return 0;
+}
+\endcode
+  *
+  */
+
+template <>
+struct NumTraits<mpfr::mpreal> : GenericNumTraits<mpfr::mpreal> {
+  enum {
+    IsInteger = 0,
+    IsSigned = 1,
+    IsComplex = 0,
+    RequireInitialization = 1,
+    ReadCost = HugeCost,
+    AddCost = HugeCost,
+    MulCost = HugeCost
+  };
+
+  typedef mpfr::mpreal Real;
+  typedef mpfr::mpreal NonInteger;
+
+  static inline Real highest(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::maxval(Precision); }
+  static inline Real lowest(long Precision = mpfr::mpreal::get_default_prec()) { return -mpfr::maxval(Precision); }
+
+  // Constants
+  static inline Real Pi(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_pi(Precision); }
+  static inline Real Euler(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_euler(Precision); }
+  static inline Real Log2(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_log2(Precision); }
+  static inline Real Catalan(long Precision = mpfr::mpreal::get_default_prec()) {
+    return mpfr::const_catalan(Precision);
+  }
+
+  static inline Real epsilon(long Precision = mpfr::mpreal::get_default_prec()) {
+    return mpfr::machine_epsilon(Precision);
+  }
+  static inline Real epsilon(const Real& x) { return mpfr::machine_epsilon(x); }
+
+#ifdef MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS
+  static inline int digits10(long Precision = mpfr::mpreal::get_default_prec()) {
+    return std::numeric_limits<Real>::digits10(Precision);
+  }
+  static inline int digits10(const Real& x) { return std::numeric_limits<Real>::digits10(x); }
+
+  static inline int max_digits10(long Precision = mpfr::mpreal::get_default_prec()) {
+    return std::numeric_limits<Real>::max_digits10(Precision);
+  }
+
+  static inline int digits() { return std::numeric_limits<Real>::digits(); }
+  static inline int digits(const Real& x) { return std::numeric_limits<Real>::digits(x); }
+#endif
+
+  static inline Real dummy_precision() {
+    mpfr_prec_t weak_prec = ((mpfr::mpreal::get_default_prec() - 1) * 90) / 100;
+    return mpfr::machine_epsilon(weak_prec);
+  }
+};
+
+namespace internal {
+
+template <>
+inline mpfr::mpreal random<mpfr::mpreal>() {
+  return mpfr::random();
+}
+
+template <>
+inline mpfr::mpreal random<mpfr::mpreal>(const mpfr::mpreal& a, const mpfr::mpreal& b) {
+  return a + (b - a) * random<mpfr::mpreal>();
+}
+
+inline bool isMuchSmallerThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps) {
+  return mpfr::abs(a) <= mpfr::abs(b) * eps;
+}
+
+inline bool isApprox(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps) {
+  return mpfr::isEqualFuzzy(a, b, eps);
+}
+
+inline bool isApproxOrLessThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps) {
+  return a <= b || mpfr::isEqualFuzzy(a, b, eps);
+}
+
+template <>
+inline long double cast<mpfr::mpreal, long double>(const mpfr::mpreal& x) {
+  return x.toLDouble();
+}
+
+template <>
+inline double cast<mpfr::mpreal, double>(const mpfr::mpreal& x) {
+  return x.toDouble();
+}
+
+template <>
+inline long cast<mpfr::mpreal, long>(const mpfr::mpreal& x) {
+  return x.toLong();
+}
+
+template <>
+inline int cast<mpfr::mpreal, int>(const mpfr::mpreal& x) {
+  return int(x.toLong());
+}
+
+// Specialize GEBP kernel and traits for mpreal (no need for peeling, nor complicated stuff)
+// This also permits to directly call mpfr's routines and avoid many temporaries produced by mpreal
+template <>
+class gebp_traits<mpfr::mpreal, mpfr::mpreal, false, false> {
+ public:
+  typedef mpfr::mpreal ResScalar;
+  enum {
+    Vectorizable = false,
+    LhsPacketSize = 1,
+    RhsPacketSize = 1,
+    ResPacketSize = 1,
+    NumberOfRegisters = 1,
+    nr = 1,
+    mr = 1,
+    LhsProgress = 1,
+    RhsProgress = 1
+  };
+  typedef ResScalar LhsPacket;
+  typedef ResScalar RhsPacket;
+  typedef ResScalar ResPacket;
+  typedef LhsPacket LhsPacket4Packing;
+};
+
+template <typename Index, typename DataMapper, bool ConjugateLhs, bool ConjugateRhs>
+struct gebp_kernel<mpfr::mpreal, mpfr::mpreal, Index, DataMapper, 1, 1, ConjugateLhs, ConjugateRhs> {
+  typedef mpfr::mpreal mpreal;
+
+  EIGEN_DONT_INLINE void operator()(const DataMapper& res, const mpreal* blockA, const mpreal* blockB, Index rows,
+                                    Index depth, Index cols, const mpreal& alpha, Index strideA = -1,
+                                    Index strideB = -1, Index offsetA = 0, Index offsetB = 0) {
+    if (rows == 0 || cols == 0 || depth == 0) return;
+
+    mpreal acc1(0, mpfr_get_prec(blockA[0].mpfr_srcptr())), tmp(0, mpfr_get_prec(blockA[0].mpfr_srcptr()));
+
+    if (strideA == -1) strideA = depth;
+    if (strideB == -1) strideB = depth;
+
+    for (Index i = 0; i < rows; ++i) {
+      for (Index j = 0; j < cols; ++j) {
+        const mpreal* A = blockA + i * strideA + offsetA;
+        const mpreal* B = blockB + j * strideB + offsetB;
+
+        acc1 = 0;
+        for (Index k = 0; k < depth; k++) {
+          mpfr_mul(tmp.mpfr_ptr(), A[k].mpfr_srcptr(), B[k].mpfr_srcptr(), mpreal::get_default_rnd());
+          mpfr_add(acc1.mpfr_ptr(), acc1.mpfr_ptr(), tmp.mpfr_ptr(), mpreal::get_default_rnd());
+        }
+
+        mpfr_mul(acc1.mpfr_ptr(), acc1.mpfr_srcptr(), alpha.mpfr_srcptr(), mpreal::get_default_rnd());
+        mpfr_add(res(i, j).mpfr_ptr(), res(i, j).mpfr_srcptr(), acc1.mpfr_srcptr(), mpreal::get_default_rnd());
+      }
+    }
+  }
+};
+}  // end namespace internal
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_MPREALSUPPORT_MODULE_H
diff --git a/contrib/Eigen/MatrixFunctions b/contrib/Eigen/MatrixFunctions
new file mode 100644
index 0000000..294d541
--- /dev/null
+++ b/contrib/Eigen/MatrixFunctions
@@ -0,0 +1,505 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Jitse Niesen <jitse@maths.leeds.ac.uk>
+// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
+//
+// 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
+
+#ifndef EIGEN_MATRIX_FUNCTIONS_MODULE_H
+#define EIGEN_MATRIX_FUNCTIONS_MODULE_H
+
+#include <cfloat>
+#include <list>
+
+#include "../../Eigen/Core"
+#include "../../Eigen/LU"
+#include "../../Eigen/Eigenvalues"
+
+/**
+ * \defgroup MatrixFunctions_Module Matrix functions module
+ * \brief This module aims to provide various methods for the computation of
+ * matrix functions.
+ *
+ * To use this module, add
+ * \code
+ * #include <contrib/Eigen/MatrixFunctions>
+ * \endcode
+ * at the start of your source file.
+ *
+ * This module defines the following MatrixBase methods.
+ *  - \ref matrixbase_cos "MatrixBase::cos()", for computing the matrix cosine
+ *  - \ref matrixbase_cosh "MatrixBase::cosh()", for computing the matrix hyperbolic cosine
+ *  - \ref matrixbase_exp "MatrixBase::exp()", for computing the matrix exponential
+ *  - \ref matrixbase_log "MatrixBase::log()", for computing the matrix logarithm
+ *  - \ref matrixbase_pow "MatrixBase::pow()", for computing the matrix power
+ *  - \ref matrixbase_matrixfunction "MatrixBase::matrixFunction()", for computing general matrix functions
+ *  - \ref matrixbase_sin "MatrixBase::sin()", for computing the matrix sine
+ *  - \ref matrixbase_sinh "MatrixBase::sinh()", for computing the matrix hyperbolic sine
+ *  - \ref matrixbase_sqrt "MatrixBase::sqrt()", for computing the matrix square root
+ *
+ * These methods are the main entry points to this module.
+ *
+ * %Matrix functions are defined as follows.  Suppose that \f$ f \f$
+ * is an entire function (that is, a function on the complex plane
+ * that is everywhere complex differentiable).  Then its Taylor
+ * series
+ * \f[ f(0) + f'(0) x + \frac{f''(0)}{2} x^2 + \frac{f'''(0)}{3!} x^3 + \cdots \f]
+ * converges to \f$ f(x) \f$. In this case, we can define the matrix
+ * function by the same series:
+ * \f[ f(M) = f(0) + f'(0) M + \frac{f''(0)}{2} M^2 + \frac{f'''(0)}{3!} M^3 + \cdots \f]
+ *
+ */
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/MatrixFunctions/MatrixExponential.h"
+#include "src/MatrixFunctions/MatrixFunction.h"
+#include "src/MatrixFunctions/MatrixSquareRoot.h"
+#include "src/MatrixFunctions/MatrixLogarithm.h"
+#include "src/MatrixFunctions/MatrixPower.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+/**
+\page matrixbaseextra_page
+\ingroup MatrixFunctions_Module
+
+\section matrixbaseextra MatrixBase methods defined in the MatrixFunctions module
+
+The remainder of the page documents the following MatrixBase methods
+which are defined in the MatrixFunctions module.
+
+
+
+\subsection matrixbase_cos MatrixBase::cos()
+
+Compute the matrix cosine.
+
+\code
+const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cos() const
+\endcode
+
+\param[in]  M  a square matrix.
+\returns  expression representing \f$ \cos(M) \f$.
+
+This function computes the matrix cosine. Use ArrayBase::cos() for computing the entry-wise cosine.
+
+The implementation calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cos().
+
+\sa \ref matrixbase_sin "sin()" for an example.
+
+
+
+\subsection matrixbase_cosh MatrixBase::cosh()
+
+Compute the matrix hyberbolic cosine.
+
+\code
+const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cosh() const
+\endcode
+
+\param[in]  M  a square matrix.
+\returns  expression representing \f$ \cosh(M) \f$
+
+This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cosh().
+
+\sa \ref matrixbase_sinh "sinh()" for an example.
+
+
+
+\subsection matrixbase_exp MatrixBase::exp()
+
+Compute the matrix exponential.
+
+\code
+const MatrixExponentialReturnValue<Derived> MatrixBase<Derived>::exp() const
+\endcode
+
+\param[in]  M  matrix whose exponential is to be computed.
+\returns    expression representing the matrix exponential of \p M.
+
+The matrix exponential of \f$ M \f$ is defined by
+\f[ \exp(M) = \sum_{k=0}^\infty \frac{M^k}{k!}. \f]
+The matrix exponential can be used to solve linear ordinary
+differential equations: the solution of \f$ y' = My \f$ with the
+initial condition \f$ y(0) = y_0 \f$ is given by
+\f$ y(t) = \exp(M) y_0 \f$.
+
+The matrix exponential is different from applying the exp function to all the entries in the matrix.
+Use ArrayBase::exp() if you want to do the latter.
+
+The cost of the computation is approximately \f$ 20 n^3 \f$ for
+matrices of size \f$ n \f$. The number 20 depends weakly on the
+norm of the matrix.
+
+The matrix exponential is computed using the scaling-and-squaring
+method combined with Pad&eacute; approximation. The matrix is first
+rescaled, then the exponential of the reduced matrix is computed
+approximant, and then the rescaling is undone by repeated
+squaring. The degree of the Pad&eacute; approximant is chosen such
+that the approximation error is less than the round-off
+error. However, errors may accumulate during the squaring phase.
+
+Details of the algorithm can be found in: Nicholas J. Higham, "The
+scaling and squaring method for the matrix exponential revisited,"
+<em>SIAM J. %Matrix Anal. Applic.</em>, <b>26</b>:1179&ndash;1193,
+2005.
+
+Example: The following program checks that
+\f[ \exp \left[ \begin{array}{ccc}
+      0 & \frac14\pi & 0 \\
+      -\frac14\pi & 0 & 0 \\
+      0 & 0 & 0
+    \end{array} \right] = \left[ \begin{array}{ccc}
+      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
+      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
+      0 & 0 & 1
+    \end{array} \right]. \f]
+This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
+the z-axis.
+
+\include MatrixExponential.cpp
+Output: \verbinclude MatrixExponential.out
+
+\note \p M has to be a matrix of \c float, \c double, `long double`
+\c complex<float>, \c complex<double>, or `complex<long double>` .
+
+
+\subsection matrixbase_log MatrixBase::log()
+
+Compute the matrix logarithm.
+
+\code
+const MatrixLogarithmReturnValue<Derived> MatrixBase<Derived>::log() const
+\endcode
+
+\param[in]  M  invertible matrix whose logarithm is to be computed.
+\returns    expression representing the matrix logarithm root of \p M.
+
+The matrix logarithm of \f$ M \f$ is a matrix \f$ X \f$ such that
+\f$ \exp(X) = M \f$ where exp denotes the matrix exponential. As for
+the scalar logarithm, the equation \f$ \exp(X) = M \f$ may have
+multiple solutions; this function returns a matrix whose eigenvalues
+have imaginary part in the interval \f$ (-\pi,\pi] \f$.
+
+The matrix logarithm is different from applying the log function to all the entries in the matrix.
+Use ArrayBase::log() if you want to do the latter.
+
+In the real case, the matrix \f$ M \f$ should be invertible and
+it should have no eigenvalues which are real and negative (pairs of
+complex conjugate eigenvalues are allowed). In the complex case, it
+only needs to be invertible.
+
+This function computes the matrix logarithm using the Schur-Parlett
+algorithm as implemented by MatrixBase::matrixFunction(). The
+logarithm of an atomic block is computed by MatrixLogarithmAtomic,
+which uses direct computation for 1-by-1 and 2-by-2 blocks and an
+inverse scaling-and-squaring algorithm for bigger blocks, with the
+square roots computed by MatrixBase::sqrt().
+
+Details of the algorithm can be found in Section 11.6.2 of:
+Nicholas J. Higham,
+<em>Functions of Matrices: Theory and Computation</em>,
+SIAM 2008. ISBN 978-0-898716-46-7.
+
+Example: The following program checks that
+\f[ \log \left[ \begin{array}{ccc}
+      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
+      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
+      0 & 0 & 1
+    \end{array} \right] = \left[ \begin{array}{ccc}
+      0 & \frac14\pi & 0 \\
+      -\frac14\pi & 0 & 0 \\
+      0 & 0 & 0
+    \end{array} \right]. \f]
+This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
+the z-axis. This is the inverse of the example used in the
+documentation of \ref matrixbase_exp "exp()".
+
+\include MatrixLogarithm.cpp
+Output: \verbinclude MatrixLogarithm.out
+
+\note \p M has to be a matrix of \c float, \c double, `long
+double`, \c complex<float>, \c complex<double>, or `complex<long double>`.
+
+\sa MatrixBase::exp(), MatrixBase::matrixFunction(),
+    class MatrixLogarithmAtomic, MatrixBase::sqrt().
+
+
+\subsection matrixbase_pow MatrixBase::pow()
+
+Compute the matrix raised to arbitrary real power.
+
+\code
+const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(RealScalar p) const
+\endcode
+
+\param[in]  M  base of the matrix power, should be a square matrix.
+\param[in]  p  exponent of the matrix power.
+
+The matrix power \f$ M^p \f$ is defined as \f$ \exp(p \log(M)) \f$,
+where exp denotes the matrix exponential, and log denotes the matrix
+logarithm. This is different from raising all the entries in the matrix
+to the p-th power. Use ArrayBase::pow() if you want to do the latter.
+
+If \p p is complex, the scalar type of \p M should be the type of \p
+p . \f$ M^p \f$ simply evaluates into \f$ \exp(p \log(M)) \f$.
+Therefore, the matrix \f$ M \f$ should meet the conditions to be an
+argument of matrix logarithm.
+
+If \p p is real, it is casted into the real scalar type of \p M. Then
+this function computes the matrix power using the Schur-Pad&eacute;
+algorithm as implemented by class MatrixPower. The exponent is split
+into integral part and fractional part, where the fractional part is
+in the interval \f$ (-1, 1) \f$. The main diagonal and the first
+super-diagonal is directly computed.
+
+If \p M is singular with a semisimple zero eigenvalue and \p p is
+positive, the Schur factor \f$ T \f$ is reordered with Givens
+rotations, i.e.
+
+\f[ T = \left[ \begin{array}{cc}
+      T_1 & T_2 \\
+      0   & 0
+    \end{array} \right] \f]
+
+where \f$ T_1 \f$ is invertible. Then \f$ T^p \f$ is given by
+
+\f[ T^p = \left[ \begin{array}{cc}
+      T_1^p & T_1^{-1} T_1^p T_2 \\
+      0     & 0
+    \end{array}. \right] \f]
+
+\warning Fractional power of a matrix with a non-semisimple zero
+eigenvalue is not well-defined. We introduce an assertion failure
+against inaccurate result, e.g. \code
+#include <contrib/Eigen/MatrixFunctions>
+#include <iostream>
+
+int main()
+{
+  Eigen::Matrix4d A;
+  A << 0, 0, 2, 3,
+       0, 0, 4, 5,
+       0, 0, 6, 7,
+       0, 0, 8, 9;
+  std::cout << A.pow(0.37) << std::endl;
+
+  // The 1 makes eigenvalue 0 non-semisimple.
+  A.coeffRef(0, 1) = 1;
+
+  // This fails if EIGEN_NO_DEBUG is undefined.
+  std::cout << A.pow(0.37) << std::endl;
+
+  return 0;
+}
+\endcode
+
+Details of the algorithm can be found in: Nicholas J. Higham and
+Lijing Lin, "A Schur-Pad&eacute; algorithm for fractional powers of a
+matrix," <em>SIAM J. %Matrix Anal. Applic.</em>,
+<b>32(3)</b>:1056&ndash;1078, 2011.
+
+Example: The following program checks that
+\f[ \left[ \begin{array}{ccc}
+      \cos1 & -\sin1 & 0 \\
+      \sin1 & \cos1 & 0 \\
+      0 & 0 & 1
+    \end{array} \right]^{\frac14\pi} = \left[ \begin{array}{ccc}
+      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
+      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
+      0 & 0 & 1
+    \end{array} \right]. \f]
+This corresponds to \f$ \frac14\pi \f$ rotations of 1 radian around
+the z-axis.
+
+\include MatrixPower.cpp
+Output: \verbinclude MatrixPower.out
+
+MatrixBase::pow() is user-friendly. However, there are some
+circumstances under which you should use class MatrixPower directly.
+MatrixPower can save the result of Schur decomposition, so it's
+better for computing various powers for the same matrix.
+
+Example:
+\include MatrixPower_optimal.cpp
+Output: \verbinclude MatrixPower_optimal.out
+
+\note \p M has to be a matrix of \c float, \c double, `long
+double`, \c complex<float>, \c complex<double>, or
+\c complex<long double> .
+
+\sa MatrixBase::exp(), MatrixBase::log(), class MatrixPower.
+
+
+\subsection matrixbase_matrixfunction MatrixBase::matrixFunction()
+
+Compute a matrix function.
+
+\code
+const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::matrixFunction(typename internal::stem_function<typename
+internal::traits<Derived>::Scalar>::type f) const \endcode
+
+\param[in]  M  argument of matrix function, should be a square matrix.
+\param[in]  f  an entire function; \c f(x,n) should compute the n-th
+derivative of f at x.
+\returns  expression representing \p f applied to \p M.
+
+Suppose that \p M is a matrix whose entries have type \c Scalar.
+Then, the second argument, \p f, should be a function with prototype
+\code
+ComplexScalar f(ComplexScalar, int)
+\endcode
+where \c ComplexScalar = \c std::complex<Scalar> if \c Scalar is
+real (e.g., \c float or \c double) and \c ComplexScalar =
+\c Scalar if \c Scalar is complex. The return value of \c f(x,n)
+should be \f$ f^{(n)}(x) \f$, the n-th derivative of f at x.
+
+This routine uses the algorithm described in:
+Philip Davies and Nicholas J. Higham,
+"A Schur-Parlett algorithm for computing matrix functions",
+<em>SIAM J. %Matrix Anal. Applic.</em>, <b>25</b>:464&ndash;485, 2003.
+
+The actual work is done by the MatrixFunction class.
+
+Example: The following program checks that
+\f[ \exp \left[ \begin{array}{ccc}
+      0 & \frac14\pi & 0 \\
+      -\frac14\pi & 0 & 0 \\
+      0 & 0 & 0
+    \end{array} \right] = \left[ \begin{array}{ccc}
+      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
+      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
+      0 & 0 & 1
+    \end{array} \right]. \f]
+This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
+the z-axis. This is the same example as used in the documentation
+of \ref matrixbase_exp "exp()".
+
+\include MatrixFunction.cpp
+Output: \verbinclude MatrixFunction.out
+
+Note that the function \c expfn is defined for complex numbers
+\c x, even though the matrix \c A is over the reals. Instead of
+\c expfn, we could also have used StdStemFunctions::exp:
+\code
+A.matrixFunction(StdStemFunctions<std::complex<double> >::exp, &B);
+\endcode
+
+
+
+\subsection matrixbase_sin MatrixBase::sin()
+
+Compute the matrix sine.
+
+\code
+const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sin() const
+\endcode
+
+\param[in]  M  a square matrix.
+\returns  expression representing \f$ \sin(M) \f$.
+
+This function computes the matrix sine. Use ArrayBase::sin() for computing the entry-wise sine.
+
+The implementation calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sin().
+
+Example: \include MatrixSine.cpp
+Output: \verbinclude MatrixSine.out
+
+
+
+\subsection matrixbase_sinh MatrixBase::sinh()
+
+Compute the matrix hyperbolic sine.
+
+\code
+MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sinh() const
+\endcode
+
+\param[in]  M  a square matrix.
+\returns  expression representing \f$ \sinh(M) \f$
+
+This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sinh().
+
+Example: \include MatrixSinh.cpp
+Output: \verbinclude MatrixSinh.out
+
+
+\subsection matrixbase_sqrt MatrixBase::sqrt()
+
+Compute the matrix square root.
+
+\code
+const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const
+\endcode
+
+\param[in]  M  invertible matrix whose square root is to be computed.
+\returns    expression representing the matrix square root of \p M.
+
+The matrix square root of \f$ M \f$ is the matrix \f$ M^{1/2} \f$
+whose square is the original matrix; so if \f$ S = M^{1/2} \f$ then
+\f$ S^2 = M \f$. This is different from taking the square root of all
+the entries in the matrix; use ArrayBase::sqrt() if you want to do the
+latter.
+
+In the <b>real case</b>, the matrix \f$ M \f$ should be invertible and
+it should have no eigenvalues which are real and negative (pairs of
+complex conjugate eigenvalues are allowed). In that case, the matrix
+has a square root which is also real, and this is the square root
+computed by this function.
+
+The matrix square root is computed by first reducing the matrix to
+quasi-triangular form with the real Schur decomposition. The square
+root of the quasi-triangular matrix can then be computed directly. The
+cost is approximately \f$ 25 n^3 \f$ real flops for the real Schur
+decomposition and \f$ 3\frac13 n^3 \f$ real flops for the remainder
+(though the computation time in practice is likely more than this
+indicates).
+
+Details of the algorithm can be found in: Nicholas J. Highan,
+"Computing real square roots of a real matrix", <em>Linear Algebra
+Appl.</em>, 88/89:405&ndash;430, 1987.
+
+If the matrix is <b>positive-definite symmetric</b>, then the square
+root is also positive-definite symmetric. In this case, it is best to
+use SelfAdjointEigenSolver::operatorSqrt() to compute it.
+
+In the <b>complex case</b>, the matrix \f$ M \f$ should be invertible;
+this is a restriction of the algorithm. The square root computed by
+this algorithm is the one whose eigenvalues have an argument in the
+interval \f$ (-\frac12\pi, \frac12\pi] \f$. This is the usual branch
+cut.
+
+The computation is the same as in the real case, except that the
+complex Schur decomposition is used to reduce the matrix to a
+triangular matrix. The theoretical cost is the same. Details are in:
+&Aring;ke Bj&ouml;rck and Sven Hammarling, "A Schur method for the
+square root of a matrix", <em>Linear Algebra Appl.</em>,
+52/53:127&ndash;140, 1983.
+
+Example: The following program checks that the square root of
+\f[ \left[ \begin{array}{cc}
+              \cos(\frac13\pi) & -\sin(\frac13\pi) \\
+              \sin(\frac13\pi) & \cos(\frac13\pi)
+    \end{array} \right], \f]
+corresponding to a rotation over 60 degrees, is a rotation over 30 degrees:
+\f[ \left[ \begin{array}{cc}
+              \cos(\frac16\pi) & -\sin(\frac16\pi) \\
+              \sin(\frac16\pi) & \cos(\frac16\pi)
+    \end{array} \right]. \f]
+
+\include MatrixSquareRoot.cpp
+Output: \verbinclude MatrixSquareRoot.out
+
+\sa class RealSchur, class ComplexSchur, class MatrixSquareRoot,
+    SelfAdjointEigenSolver::operatorSqrt().
+
+*/
+
+#endif  // EIGEN_MATRIX_FUNCTIONS_MODULE_H
diff --git a/contrib/Eigen/NNLS b/contrib/Eigen/NNLS
new file mode 100644
index 0000000..d1c9cfb
--- /dev/null
+++ b/contrib/Eigen/NNLS
@@ -0,0 +1,416 @@
+/* Non-Negagive Least Squares Algorithm for Eigen.
+ *
+ * Copyright (C) 2021 Essex Edwards, <essex.edwards@gmail.com>
+ * Copyright (C) 2013 Hannes Matuschek, hannes.matuschek at uni-potsdam.de
+ *
+ * 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
+
+/** \defgroup nnls Non-Negative Least Squares (NNLS) Module
+ * This module provides a single class @c Eigen::NNLS implementing the NNLS algorithm.
+ * The algorithm is described in "SOLVING LEAST SQUARES PROBLEMS", by Charles L. Lawson and
+ * Richard J. Hanson, Prentice-Hall, 1974 and solves optimization problems of the form
+ *
+ * \f[ \min \left\Vert Ax-b\right\Vert_2^2\quad s.t.\, x\ge 0\,.\f]
+ *
+ * The algorithm solves the constrained least-squares problem above by iteratively improving
+ * an estimate of which constraints are active (elements of \f$x\f$ equal to zero)
+ * and which constraints are inactive (elements of \f$x\f$ greater than zero).
+ * Each iteration, an unconstrained linear least-squares problem solves for the
+ * components of \f$x\f$ in the (estimated) inactive set and the sets are updated.
+ * The unconstrained problem minimizes \f$\left\Vert A^Nx^N-b\right\Vert_2^2\f$,
+ * where \f$A^N\f$ is a matrix formed by selecting all columns of A which are
+ * in the inactive set \f$N\f$.
+ *
+ */
+
+#ifndef EIGEN_NNLS_MODULE_H
+#define EIGEN_NNLS_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/QR"
+
+#include <limits>
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/** \ingroup nnls
+ * \class NNLS
+ * \brief Implementation of the Non-Negative Least Squares (NNLS) algorithm.
+ * \tparam MatrixType The type of the system matrix \f$A\f$.
+ *
+ * This class implements the NNLS algorithm as described in "SOLVING LEAST SQUARES PROBLEMS",
+ * Charles L. Lawson and Richard J. Hanson, Prentice-Hall, 1974. This algorithm solves a least
+ * squares problem iteratively and ensures that the solution is non-negative. I.e.
+ *
+ * \f[ \min \left\Vert Ax-b\right\Vert_2^2\quad s.t.\, x\ge 0 \f]
+ *
+ * The algorithm solves the constrained least-squares problem above by iteratively improving
+ * an estimate of which constraints are active (elements of \f$x\f$ equal to zero)
+ * and which constraints are inactive (elements of \f$x\f$ greater than zero).
+ * Each iteration, an unconstrained linear least-squares problem solves for the
+ * components of \f$x\f$ in the (estimated) inactive set and the sets are updated.
+ * The unconstrained problem minimizes \f$\left\Vert A^Nx^N-b\right\Vert_2^2\f$,
+ * where \f$A^N\f$ is a matrix formed by selecting all columns of A which are
+ * in the inactive set \f$N\f$.
+ *
+ * See <a href="https://en.wikipedia.org/wiki/Non-negative_least_squares">the
+ * wikipedia page on non-negative least squares</a> for more background information.
+ *
+ * \note Please note that it is possible to construct an NNLS problem for which the
+ *       algorithm does not converge. In practice these cases are extremely rare.
+ */
+template <class MatrixType_>
+class NNLS {
+ public:
+  typedef MatrixType_ MatrixType;
+
+  enum {
+    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+    ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+    Options = MatrixType::Options,
+    MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+    MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
+  };
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef typename MatrixType::Index Index;
+
+  /** Type of a row vector of the system matrix \f$A\f$. */
+  typedef Matrix<Scalar, ColsAtCompileTime, 1> SolutionVectorType;
+  /** Type of a column vector of the system matrix \f$A\f$. */
+  typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsVectorType;
+  typedef Matrix<Index, ColsAtCompileTime, 1> IndicesType;
+
+  /** */
+  NNLS();
+
+  /** \brief Constructs a NNLS solver and initializes it with the given system matrix @c A.
+   * \param A Specifies the system matrix.
+   * \param max_iter Specifies the maximum number of iterations to solve the system.
+   * \param tol Specifies the precision of the optimum.
+   *        This is an absolute tolerance on the gradient of the Lagrangian, \f$A^T(Ax-b)-\lambda\f$
+   *        (with Lagrange multipliers \f$\lambda\f$).
+   */
+  NNLS(const MatrixType &A, Index max_iter = -1, Scalar tol = NumTraits<Scalar>::dummy_precision());
+
+  /** Initializes the solver with the matrix \a A for further solving NNLS problems.
+   *
+   * This function mostly initializes/computes the preconditioner. In the future
+   * we might, for instance, implement column reordering for faster matrix vector products.
+   */
+  template <typename MatrixDerived>
+  NNLS<MatrixType> &compute(const EigenBase<MatrixDerived> &A);
+
+  /** \brief Solves the NNLS problem.
+   *
+   * The dimension of @c b must be equal to the number of rows of @c A, given to the constructor.
+   *
+   * \returns The approximate solution vector \f$ x \f$. Use info() to determine if the solve was a success or not.
+   * \sa info()
+   */
+  const SolutionVectorType &solve(const RhsVectorType &b);
+
+  /** \brief Returns the solution if a problem was solved.
+   * If not, an uninitialized vector may be returned. */
+  const SolutionVectorType &x() const { return x_; }
+
+  /** \returns the tolerance threshold used by the stopping criteria.
+   * \sa setTolerance()
+   */
+  Scalar tolerance() const { return tolerance_; }
+
+  /** Sets the tolerance threshold used by the stopping criteria.
+   *
+   * This is an absolute tolerance on the gradient of the Lagrangian, \f$A^T(Ax-b)-\lambda\f$
+   * (with Lagrange multipliers \f$\lambda\f$).
+   */
+  NNLS<MatrixType> &setTolerance(const Scalar &tolerance) {
+    tolerance_ = tolerance;
+    return *this;
+  }
+
+  /** \returns the max number of iterations.
+   * It is either the value set by setMaxIterations or, by default, twice the number of columns of the matrix.
+   */
+  Index maxIterations() const { return max_iter_ < 0 ? 2 * A_.cols() : max_iter_; }
+
+  /** Sets the max number of iterations.
+   * Default is twice the number of columns of the matrix.
+   * The algorithm requires at least k iterations to produce a solution vector with k non-zero entries.
+   */
+  NNLS<MatrixType> &setMaxIterations(Index maxIters) {
+    max_iter_ = maxIters;
+    return *this;
+  }
+
+  /** \returns the number of iterations (least-squares solves) performed during the last solve */
+  Index iterations() const { return iterations_; }
+
+  /** \returns Success if the iterations converged, and an error values otherwise. */
+  ComputationInfo info() const { return info_; }
+
+ private:
+  /** \internal Adds the given index @c idx to the inactive set N and updates the QR decomposition of \f$A^N\f$. */
+  void moveToInactiveSet_(Index idx);
+
+  /** \internal Removes the given index idx from the inactive set N and updates the QR decomposition of \f$A^N\f$. */
+  void moveToActiveSet_(Index idx);
+
+  /** \internal Solves the least-squares problem \f$\left\Vert y-A^Nx\right\Vert_2^2\f$. */
+  void solveInactiveSet_(const RhsVectorType &b);
+
+ private:
+  typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixAtAType;
+
+  /** \internal Holds the maximum number of iterations for the NNLS algorithm.
+   *  @c -1 means to use the default value. */
+  Index max_iter_;
+  /** \internal Holds the number of iterations. */
+  Index iterations_;
+  /** \internal Holds success/fail of the last solve. */
+  ComputationInfo info_;
+  /** \internal Size of the inactive set. */
+  Index numInactive_;
+  /** \internal Accuracy of the algorithm w.r.t the optimality of the solution (gradient). */
+  Scalar tolerance_;
+  /** \internal The system matrix, a copy of the one given to the constructor. */
+  MatrixType A_;
+  /** \internal Precomputed product \f$A^TA\f$. */
+  MatrixAtAType AtA_;
+  /** \internal Will hold the solution. */
+  SolutionVectorType x_;
+  /** \internal Will hold the current gradient.\f$A^Tb - A^TAx\f$ */
+  SolutionVectorType gradient_;
+  /** \internal Will hold the partial solution. */
+  SolutionVectorType y_;
+  /** \internal Precomputed product \f$A^Tb\f$. */
+  SolutionVectorType Atb_;
+  /** \internal Holds the current permutation partitioning the active and inactive sets.
+   * The first @c numInactive_ elements form the inactive set and the rest the active set. */
+  IndicesType index_sets_;
+  /** \internal QR decomposition to solve the (inactive) sub system (together with @c qrCoeffs_). */
+  MatrixType QR_;
+  /** \internal QR decomposition to solve the (inactive) sub system (together with @c QR_). */
+  SolutionVectorType qrCoeffs_;
+  /** \internal Some workspace for QR decomposition. */
+  SolutionVectorType tempSolutionVector_;
+  RhsVectorType tempRhsVector_;
+};
+
+/* ********************************************************************************************
+ * Implementation
+ * ******************************************************************************************** */
+
+template <typename MatrixType>
+NNLS<MatrixType>::NNLS()
+    : max_iter_(-1),
+      iterations_(0),
+      info_(ComputationInfo::InvalidInput),
+      numInactive_(0),
+      tolerance_(NumTraits<Scalar>::dummy_precision()) {}
+
+template <typename MatrixType>
+NNLS<MatrixType>::NNLS(const MatrixType &A, Index max_iter, Scalar tol) : max_iter_(max_iter), tolerance_(tol) {
+  compute(A);
+}
+
+template <typename MatrixType>
+template <typename MatrixDerived>
+NNLS<MatrixType> &NNLS<MatrixType>::compute(const EigenBase<MatrixDerived> &A) {
+  // Ensure Scalar type is real. The non-negativity constraint doesn't obviously extend to complex numbers.
+  EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
+
+  // max_iter_: unchanged
+  iterations_ = 0;
+  info_ = ComputationInfo::Success;
+  numInactive_ = 0;
+  // tolerance: unchanged
+  A_ = A.derived();
+  AtA_.noalias() = A_.transpose() * A_;
+  x_.resize(A_.cols());
+  gradient_.resize(A_.cols());
+  y_.resize(A_.cols());
+  Atb_.resize(A_.cols());
+  index_sets_.resize(A_.cols());
+  QR_.resize(A_.rows(), A_.cols());
+  qrCoeffs_.resize(A_.cols());
+  tempSolutionVector_.resize(A_.cols());
+  tempRhsVector_.resize(A_.rows());
+
+  return *this;
+}
+
+template <typename MatrixType>
+const typename NNLS<MatrixType>::SolutionVectorType &NNLS<MatrixType>::solve(const RhsVectorType &b) {
+  // Initialize solver
+  iterations_ = 0;
+  info_ = ComputationInfo::NumericalIssue;
+  x_.setZero();
+
+  index_sets_ = IndicesType::LinSpaced(A_.cols(), 0, A_.cols() - 1);  // Identity permutation.
+  numInactive_ = 0;
+
+  // Precompute A^T*b
+  Atb_.noalias() = A_.transpose() * b;
+
+  if (A_.rows() == 0) {
+    info_ = ComputationInfo::Success;
+    return x_;
+  }
+
+  const Index maxIterations = this->maxIterations();
+
+  // OUTER LOOP
+  while (true) {
+    // Early exit if all variables are inactive, which breaks 'maxCoeff' below.
+    if (A_.cols() == numInactive_) {
+      info_ = ComputationInfo::Success;
+      return x_;
+    }
+
+    // Find the maximum element of the gradient in the active set.
+    // If it is small or negative, then we have converged.
+    // Else, we move that variable to the inactive set.
+    gradient_.noalias() = Atb_ - AtA_ * x_;
+    if (!gradient_.allFinite()) return x_;
+
+    const Index numActive = A_.cols() - numInactive_;
+    Index argmaxGradient = -1;
+    const Scalar maxGradient = gradient_(index_sets_.tail(numActive)).maxCoeff(&argmaxGradient);
+    argmaxGradient += numInactive_;  // because tail() skipped the first numInactive_ elements
+
+    if (maxGradient < tolerance_) {
+      info_ = ComputationInfo::Success;
+      return x_;
+    }
+
+    if (iterations_ >= maxIterations) {
+      info_ = ComputationInfo::NoConvergence;
+      return x_;
+    }
+
+    // In exact arithmetic, a positive gradient guarantees that the candidate
+    // column is independent of the inactive (passive) set, so a row-sized set
+    // would have satisfied the stopping condition above. If it does not,
+    // numerical dependence has invalidated that invariant. Another rank-1 QR
+    // update would exceed the row capacity, but the current iterate cannot be
+    // reported as optimal either.
+    if (numInactive_ == A_.rows()) {
+      info_ = ComputationInfo::NumericalIssue;
+      return x_;
+    }
+
+    moveToInactiveSet_(argmaxGradient);
+
+    // INNER LOOP
+    while (true) {
+      // Check if max. number of iterations is reached
+      if (iterations_ >= maxIterations) {
+        info_ = ComputationInfo::NoConvergence;
+        return x_;
+      }
+
+      // Solve least-squares problem in inactive set only,
+      // this step is rather trivial as moveToInactiveSet_ & moveToActiveSet_
+      // updates the QR decomposition of inactive columns A^N.
+      // solveInactiveSet_ puts the solution in y_
+      solveInactiveSet_(b);
+      ++iterations_;  // The solve is expensive, so that is what we count as an iteration.
+      if (!y_.allFinite()) return x_;
+
+      // Check feasibility...
+      bool feasible = true;
+      Scalar alpha = NumTraits<Scalar>::highest();
+      Index infeasibleIdx = -1;  // Which variable became infeasible first.
+      for (Index i = 0; i < numInactive_; i++) {
+        Index idx = index_sets_[i];
+        if (y_(idx) < 0) {
+          // t should always be in [0,1].
+          Scalar t = -x_(idx) / (y_(idx) - x_(idx));
+          if (alpha > t) {
+            alpha = t;
+            infeasibleIdx = i;
+            feasible = false;
+          }
+        }
+      }
+      eigen_assert(feasible || 0 <= infeasibleIdx);
+
+      // If solution is feasible, exit to outer loop
+      if (feasible) {
+        x_ = y_;
+        break;
+      }
+
+      // Infeasible solution -> interpolate to feasible one
+      for (Index i = 0; i < numInactive_; i++) {
+        Index idx = index_sets_[i];
+        x_(idx) += alpha * (y_(idx) - x_(idx));
+      }
+
+      // Remove these indices from the inactive set and update QR decomposition
+      moveToActiveSet_(infeasibleIdx);
+    }
+  }
+}
+
+template <typename MatrixType>
+void NNLS<MatrixType>::moveToInactiveSet_(Index idx) {
+  // Update permutation matrix:
+  std::swap(index_sets_(idx), index_sets_(numInactive_));
+  numInactive_++;
+
+  // Perform rank-1 update of the QR decomposition stored in QR_ & qrCoeff_
+  internal::householder_qr_inplace_update(QR_, qrCoeffs_, A_.col(index_sets_(numInactive_ - 1)), numInactive_ - 1,
+                                          tempSolutionVector_.data());
+}
+
+template <typename MatrixType>
+void NNLS<MatrixType>::moveToActiveSet_(Index idx) {
+  // swap index with last inactive one & reduce number of inactive columns
+  std::swap(index_sets_(idx), index_sets_(numInactive_ - 1));
+  numInactive_--;
+  // Update QR decomposition starting from the removed index up to the end [idx, ..., numInactive_]
+  for (Index i = idx; i < numInactive_; i++) {
+    Index col = index_sets_(i);
+    internal::householder_qr_inplace_update(QR_, qrCoeffs_, A_.col(col), i, tempSolutionVector_.data());
+  }
+}
+
+template <typename MatrixType>
+void NNLS<MatrixType>::solveInactiveSet_(const RhsVectorType &b) {
+  eigen_assert(numInactive_ > 0);
+
+  tempRhsVector_ = b;
+
+  // tmpRHS(0:numInactive_-1) := Q'*b
+  // tmpRHS(numInactive_:end) := useless stuff we would rather not compute at all.
+  tempRhsVector_.applyOnTheLeft(
+      householderSequence(QR_.leftCols(numInactive_), qrCoeffs_.head(numInactive_)).transpose());
+
+  // tempSol(0:numInactive_-1) := inv(R) * Q' * b
+  //  = the least-squares solution for the inactive variables.
+  tempSolutionVector_.head(numInactive_) =            //
+      QR_.topLeftCorner(numInactive_, numInactive_)   //
+          .template triangularView<Upper>()           //
+          .solve(tempRhsVector_.head(numInactive_));  //
+
+  // tempSol(numInactive_:end) := 0 = the value for the constrained variables.
+  tempSolutionVector_.tail(y_.size() - numInactive_).setZero();
+
+  // Back permute into original column order of A
+  y_.noalias() = index_sets_.asPermutation() * tempSolutionVector_.head(y_.size());
+}
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_NNLS_MODULE_H
diff --git a/contrib/Eigen/NonLinearOptimization b/contrib/Eigen/NonLinearOptimization
new file mode 100644
index 0000000..1a66a89
--- /dev/null
+++ b/contrib/Eigen/NonLinearOptimization
@@ -0,0 +1,146 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+//
+// 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
+
+#ifndef EIGEN_NONLINEAROPTIMIZATION_MODULE_H
+#define EIGEN_NONLINEAROPTIMIZATION_MODULE_H
+
+#include <vector>
+
+#include "../../Eigen/Core"
+#include "../../Eigen/Jacobi"
+#include "../../Eigen/QR"
+#include "NumericalDiff"
+
+/**
+ * \defgroup NonLinearOptimization_Module Non linear optimization module
+ *
+ * \code
+ * #include <contrib/Eigen/NonLinearOptimization>
+ * \endcode
+ *
+ * This module provides implementation of two important algorithms in non linear
+ * optimization. In both cases, we consider a system of non linear functions. Of
+ * course, this should work, and even work very well if those functions are
+ * actually linear. But if this is so, you should probably better use other
+ * methods more fitted to this special case.
+ *
+ * One algorithm allows to find a least-squares solution of such a system
+ * (Levenberg-Marquardt algorithm) and the second one is used to find
+ * a zero for the system (Powell hybrid "dogleg" method).
+ *
+ * This code is a port of minpack (http://en.wikipedia.org/wiki/MINPACK).
+ * Minpack is a very famous, old, robust and well renowned package, written in
+ * fortran. Those implementations have been carefully tuned, tested, and used
+ * for several decades.
+ *
+ * The original fortran code was automatically translated using f2c (http://en.wikipedia.org/wiki/F2c) in C,
+ * then c++, and then cleaned by several different authors.
+ * The last one of those cleanings being our starting point :
+ * http://devernay.free.fr/hacks/cminpack.html
+ *
+ * Finally, we ported this code to Eigen, creating classes and API
+ * coherent with Eigen. When possible, we switched to Eigen
+ * implementation, such as most linear algebra (vectors, matrices, stable norms).
+ *
+ * Doing so, we were very careful to check the tests we setup at the very
+ * beginning, which ensure that the same results are found.
+ *
+ * \section Tests Tests
+ *
+ * The tests are placed in the file contrib/test/NonLinear.cpp.
+ *
+ * There are two kinds of tests : those that come from examples bundled with cminpack.
+ * They guaranty we get the same results as the original algorithms (value for 'x',
+ * for the number of evaluations of the function, and for the number of evaluations
+ * of the Jacobian if ever).
+ *
+ * Other tests were added by myself at the very beginning of the
+ * process and check the results for Levenberg-Marquardt using the reference data
+ * on http://www.itl.nist.gov/div898/strd/nls/nls_main.shtml. Since then i've
+ * carefully checked that the same results were obtained when modifying the
+ * code. Please note that we do not always get the exact same decimals as they do,
+ * but this is ok : they use 128bits float, and we do the tests using the C type 'double',
+ * which is 64 bits on most platforms (x86 and amd64, at least).
+ * I've performed those tests on several other implementations of Levenberg-Marquardt, and
+ * (c)minpack performs VERY well compared to those, both in accuracy and speed.
+ *
+ * The documentation for running the tests is on the wiki
+ * http://eigen.tuxfamily.org/index.php?title=Tests
+ *
+ * \section API API: overview of methods
+ *
+ * Both algorithms needs a functor computing the Jacobian. It can be computed by
+ * hand, using auto-differentiation (see \ref AutoDiff_Module), or using numerical
+ * differences (see \ref NumericalDiff_Module). For instance:
+ *\code
+ * MyFunc func;
+ * NumericalDiff<MyFunc> func_with_num_diff(func);
+ * LevenbergMarquardt<NumericalDiff<MyFunc> > lm(func_with_num_diff);
+ * \endcode
+ * For HybridNonLinearSolver, the method solveNumericalDiff() does the above wrapping for
+ * you.
+ *
+ * The methods LevenbergMarquardt.lmder1()/lmdif1()/lmstr1() and
+ * HybridNonLinearSolver.hybrj1()/hybrd1() are specific methods from the original
+ * minpack package that you probably should NOT use until you are porting a code that
+ * was previously using minpack. They just define a 'simple' API with default values
+ * for some parameters.
+ *
+ * All algorithms are provided using two APIs :
+ *     - one where the user inits the algorithm, and uses '*OneStep()' as much as he wants :
+ * this way the caller have control over the steps
+ *     - one where the user just calls a method (optimize() or solve()) which will
+ * handle the loop: init + loop until a stop condition is met. Those are provided for
+ *  convenience.
+ *
+ * As an example, the method LevenbergMarquardt::minimize() is
+ * implemented as follow:
+ * \code
+ * Status LevenbergMarquardt<FunctorType,Scalar>::minimize(FVectorType  &x, const int mode)
+ * {
+ *     Status status = minimizeInit(x, mode);
+ *     do {
+ *         status = minimizeOneStep(x, mode);
+ *     } while (status==Running);
+ *     return status;
+ * }
+ * \endcode
+ *
+ * \section examples Examples
+ *
+ * The easiest way to understand how to use this module is by looking at the many examples in the file
+ * contrib/test/NonLinearOptimization.cpp.
+ */
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#ifndef EIGEN_PARSED_BY_DOXYGEN
+
+#include "src/NonLinearOptimization/qrsolv.h"
+#include "src/NonLinearOptimization/r1updt.h"
+#include "src/NonLinearOptimization/r1mpyq.h"
+#include "src/NonLinearOptimization/rwupdt.h"
+#include "src/NonLinearOptimization/fdjac1.h"
+#include "src/NonLinearOptimization/lmpar.h"
+#include "src/NonLinearOptimization/dogleg.h"
+#include "src/NonLinearOptimization/covar.h"
+
+#include "src/NonLinearOptimization/chkder.h"
+
+#endif
+
+#include "src/NonLinearOptimization/HybridNonLinearSolver.h"
+#include "src/NonLinearOptimization/LevenbergMarquardt.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_NONLINEAROPTIMIZATION_MODULE_H
diff --git a/contrib/Eigen/NumericalDiff b/contrib/Eigen/NumericalDiff
new file mode 100644
index 0000000..5729082
--- /dev/null
+++ b/contrib/Eigen/NumericalDiff
@@ -0,0 +1,62 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
+//
+// 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
+
+#ifndef EIGEN_NUMERICALDIFF_MODULE_H
+#define EIGEN_NUMERICALDIFF_MODULE_H
+
+#include "../../Eigen/Core"
+
+namespace Eigen {
+
+/**
+ * \defgroup NumericalDiff_Module Numerical differentiation module
+ *
+ * \code
+ * #include <contrib/Eigen/NumericalDiff>
+ * \endcode
+ *
+ * See http://en.wikipedia.org/wiki/Numerical_differentiation
+ *
+ * Warning : this should NOT be confused with automatic differentiation, which
+ * is a different method and has its own module in Eigen : \ref
+ * AutoDiff_Module.
+ *
+ * Currently only "Forward" and "Central" schemes are implemented. Those
+ * are basic methods, and there exist some more elaborated way of
+ * computing such approximates. They are implemented using both
+ * proprietary and free software, and usually requires linking to an
+ * external library. It is very easy for you to write a functor
+ * using such software, and the purpose is quite orthogonal to what we
+ * want to achieve with Eigen.
+ *
+ * This is why we will not provide wrappers for every great numerical
+ * differentiation software that exist, but should rather stick with those
+ * basic ones, that still are useful for testing.
+ *
+ * Also, the \ref NonLinearOptimization_Module needs this in order to
+ * provide full features compatibility with the original (c)minpack
+ * package.
+ *
+ */
+}
+
+//@{
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/NumericalDiff/NumericalDiff.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+//@}
+
+#endif  // EIGEN_NUMERICALDIFF_MODULE_H
diff --git a/contrib/Eigen/OpenGLSupport b/contrib/Eigen/OpenGLSupport
new file mode 100644
index 0000000..8b7f4b0
--- /dev/null
+++ b/contrib/Eigen/OpenGLSupport
@@ -0,0 +1,355 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// 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
+
+#ifndef EIGEN_OPENGL_MODULE_H
+#define EIGEN_OPENGL_MODULE_H
+
+#include "../../Eigen/Geometry"
+
+#if defined(__APPLE_CC__)
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/**
+ * \defgroup OpenGLSupport_Module OpenGL Support module
+ *
+ * This module provides wrapper functions for a couple of OpenGL functions
+ * which simplify the way to pass Eigen's object to openGL.
+ * Here is an example:
+ *
+ * \code
+ * // You need to add path_to_eigen/contrib to your include path.
+ * #include <contrib/Eigen/OpenGLSupport>
+ * // ...
+ * Vector3f x, y;
+ * Matrix3f rot;
+ *
+ * glVertex(y + x * rot);
+ *
+ * Quaternion q;
+ * glRotate(q);
+ *
+ * // ...
+ * \endcode
+ *
+ */
+//@{
+
+#define EIGEN_GL_FUNC_DECLARATION(FUNC)                                                                          \
+  namespace internal {                                                                                           \
+  template <typename XprType, typename Scalar = typename XprType::Scalar, int Rows = XprType::RowsAtCompileTime, \
+            int Cols = XprType::ColsAtCompileTime,                                                               \
+            bool IsGLCompatible = bool(internal::evaluator<XprType>::Flags & LinearAccessBit) &&                 \
+                                  bool(XprType::Flags & DirectAccessBit) &&                                      \
+                                  (XprType::IsVectorAtCompileTime || (XprType::Flags & RowMajorBit) == 0)>       \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl);                                                                 \
+                                                                                                                 \
+  template <typename XprType, typename Scalar, int Rows, int Cols>                                               \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, Scalar, Rows, Cols, false> {                            \
+    inline static void run(const XprType& p) {                                                                   \
+      EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<typename plain_matrix_type_column_major<XprType>::type>::run(p);    \
+    }                                                                                                            \
+  };                                                                                                             \
+  }                                                                                                              \
+                                                                                                                 \
+  template <typename Derived>                                                                                    \
+  inline void FUNC(const Eigen::DenseBase<Derived>& p) {                                                         \
+    EIGEN_CAT(EIGEN_CAT(internal::gl_, FUNC), _impl)<Derived>::run(p.derived());                                 \
+  }
+
+#define EIGEN_GL_FUNC_SPECIALIZATION_MAT(FUNC, SCALAR, ROWS, COLS, SUFFIX)           \
+  namespace internal {                                                               \
+  template <typename XprType>                                                        \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, ROWS, COLS, true> { \
+    inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); }             \
+  };                                                                                 \
+  }
+
+#define EIGEN_GL_FUNC_SPECIALIZATION_VEC(FUNC, SCALAR, SIZE, SUFFIX)              \
+  namespace internal {                                                            \
+  template <typename XprType>                                                     \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, SIZE, 1, true> { \
+    inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); }          \
+  };                                                                              \
+  template <typename XprType>                                                     \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, 1, SIZE, true> { \
+    inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); }          \
+  };                                                                              \
+  }
+
+EIGEN_GL_FUNC_DECLARATION(glVertex)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, int, 2, 2iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, short, 2, 2sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, float, 2, 2fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, double, 2, 2dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, int, 3, 3iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, short, 3, 3sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, float, 3, 3fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, double, 3, 3dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, int, 4, 4iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, short, 4, 4sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, float, 4, 4fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, double, 4, 4dv)
+
+EIGEN_GL_FUNC_DECLARATION(glTexCoord)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, int, 2, 2iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, short, 2, 2sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, float, 2, 2fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, double, 2, 2dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, int, 3, 3iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, short, 3, 3sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, float, 3, 3fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, double, 3, 3dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, int, 4, 4iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, short, 4, 4sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, float, 4, 4fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, double, 4, 4dv)
+
+EIGEN_GL_FUNC_DECLARATION(glColor)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, int, 2, 2iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, short, 2, 2sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, float, 2, 2fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, double, 2, 2dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, int, 3, 3iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, short, 3, 3sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, float, 3, 3fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, double, 3, 3dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, int, 4, 4iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, short, 4, 4sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, float, 4, 4fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, double, 4, 4dv)
+
+EIGEN_GL_FUNC_DECLARATION(glNormal)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, int, 3, 3iv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, short, 3, 3sv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, float, 3, 3fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, double, 3, 3dv)
+
+inline void glScale2fv(const float* v) { glScalef(v[0], v[1], 1.f); }
+inline void glScale2dv(const double* v) { glScaled(v[0], v[1], 1.0); }
+inline void glScale3fv(const float* v) { glScalef(v[0], v[1], v[2]); }
+inline void glScale3dv(const double* v) { glScaled(v[0], v[1], v[2]); }
+
+EIGEN_GL_FUNC_DECLARATION(glScale)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, float, 2, 2fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, double, 2, 2dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, float, 3, 3fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, double, 3, 3dv)
+
+template <typename Scalar>
+void glScale(const UniformScaling<Scalar>& s) {
+  glScale(Matrix<Scalar, 3, 1>::Constant(s.factor()));
+}
+
+inline void glTranslate2fv(const float* v) { glTranslatef(v[0], v[1], 0.f); }
+inline void glTranslate2dv(const double* v) { glTranslated(v[0], v[1], 0.0); }
+inline void glTranslate3fv(const float* v) { glTranslatef(v[0], v[1], v[2]); }
+inline void glTranslate3dv(const double* v) { glTranslated(v[0], v[1], v[2]); }
+
+EIGEN_GL_FUNC_DECLARATION(glTranslate)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, float, 2, 2fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, double, 2, 2dv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, float, 3, 3fv)
+EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, double, 3, 3dv)
+
+template <typename Scalar>
+void glTranslate(const Translation<Scalar, 2>& t) {
+  glTranslate(t.vector());
+}
+template <typename Scalar>
+void glTranslate(const Translation<Scalar, 3>& t) {
+  glTranslate(t.vector());
+}
+
+EIGEN_GL_FUNC_DECLARATION(glMultMatrix)
+EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix, float, 4, 4, f)
+EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix, double, 4, 4, d)
+
+template <typename Scalar>
+void glMultMatrix(const Transform<Scalar, 3, Affine>& t) {
+  glMultMatrix(t.matrix());
+}
+template <typename Scalar>
+void glMultMatrix(const Transform<Scalar, 3, Projective>& t) {
+  glMultMatrix(t.matrix());
+}
+template <typename Scalar>
+void glMultMatrix(const Transform<Scalar, 3, AffineCompact>& t) {
+  glMultMatrix(Transform<Scalar, 3, Affine>(t).matrix());
+}
+
+EIGEN_GL_FUNC_DECLARATION(glLoadMatrix)
+EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix, float, 4, 4, f)
+EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix, double, 4, 4, d)
+
+template <typename Scalar>
+void glLoadMatrix(const Transform<Scalar, 3, Affine>& t) {
+  glLoadMatrix(t.matrix());
+}
+template <typename Scalar>
+void glLoadMatrix(const Transform<Scalar, 3, Projective>& t) {
+  glLoadMatrix(t.matrix());
+}
+template <typename Scalar>
+void glLoadMatrix(const Transform<Scalar, 3, AffineCompact>& t) {
+  glLoadMatrix(Transform<Scalar, 3, Affine>(t).matrix());
+}
+
+inline void glRotate(const Rotation2D<float>& rot) { glRotatef(rot.angle() * 180.f / float(EIGEN_PI), 0.f, 0.f, 1.f); }
+inline void glRotate(const Rotation2D<double>& rot) {
+  glRotated(rot.angle() * 180.0 / double(EIGEN_PI), 0.0, 0.0, 1.0);
+}
+
+template <typename Derived>
+void glRotate(const RotationBase<Derived, 3>& rot) {
+  Transform<typename Derived::Scalar, 3, Projective> tr(rot);
+  glMultMatrix(tr.matrix());
+}
+
+#define EIGEN_GL_MAKE_CONST_const const
+#define EIGEN_GL_MAKE_CONST__
+#define EIGEN_GL_EVAL(X) X
+
+#define EIGEN_GL_FUNC1_DECLARATION(FUNC, ARG1, CONST)                                                            \
+  namespace internal {                                                                                           \
+  template <typename XprType, typename Scalar = typename XprType::Scalar, int Rows = XprType::RowsAtCompileTime, \
+            int Cols = XprType::ColsAtCompileTime,                                                               \
+            bool IsGLCompatible = bool(internal::evaluator<XprType>::Flags & LinearAccessBit) &&                 \
+                                  bool(XprType::Flags & DirectAccessBit) &&                                      \
+                                  (XprType::IsVectorAtCompileTime || (XprType::Flags & RowMajorBit) == 0)>       \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl);                                                                 \
+                                                                                                                 \
+  template <typename XprType, typename Scalar, int Rows, int Cols>                                               \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, Scalar, Rows, Cols, false> {                            \
+    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) {                      \
+      EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<typename plain_matrix_type_column_major<XprType>::type>::run(a, p); \
+    }                                                                                                            \
+  };                                                                                                             \
+  }                                                                                                              \
+                                                                                                                 \
+  template <typename Derived>                                                                                    \
+  inline void FUNC(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) Eigen::DenseBase<Derived>& p) {            \
+    EIGEN_CAT(EIGEN_CAT(internal::gl_, FUNC), _impl)<Derived>::run(a, p.derived());                              \
+  }
+
+#define EIGEN_GL_FUNC1_SPECIALIZATION_MAT(FUNC, ARG1, CONST, SCALAR, ROWS, COLS, SUFFIX)    \
+  namespace internal {                                                                      \
+  template <typename XprType>                                                               \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, ROWS, COLS, true> {        \
+    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
+      FUNC##SUFFIX(a, p.data());                                                            \
+    }                                                                                       \
+  };                                                                                        \
+  }
+
+#define EIGEN_GL_FUNC1_SPECIALIZATION_VEC(FUNC, ARG1, CONST, SCALAR, SIZE, SUFFIX)          \
+  namespace internal {                                                                      \
+  template <typename XprType>                                                               \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, SIZE, 1, true> {           \
+    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
+      FUNC##SUFFIX(a, p.data());                                                            \
+    }                                                                                       \
+  };                                                                                        \
+  template <typename XprType>                                                               \
+  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, 1, SIZE, true> {           \
+    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
+      FUNC##SUFFIX(a, p.data());                                                            \
+    }                                                                                       \
+  };                                                                                        \
+  }
+
+EIGEN_GL_FUNC1_DECLARATION(glGet, GLenum, _)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glGet, GLenum, _, float, 4, 4, Floatv)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glGet, GLenum, _, double, 4, 4, Doublev)
+
+// glUniform API
+
+#ifdef GL_VERSION_2_0
+
+inline void glUniform2fv_ei(GLint loc, const float* v) { glUniform2fv(loc, 1, v); }
+inline void glUniform2iv_ei(GLint loc, const int* v) { glUniform2iv(loc, 1, v); }
+
+inline void glUniform3fv_ei(GLint loc, const float* v) { glUniform3fv(loc, 1, v); }
+inline void glUniform3iv_ei(GLint loc, const int* v) { glUniform3iv(loc, 1, v); }
+
+inline void glUniform4fv_ei(GLint loc, const float* v) { glUniform4fv(loc, 1, v); }
+inline void glUniform4iv_ei(GLint loc, const int* v) { glUniform4iv(loc, 1, v); }
+
+inline void glUniformMatrix2fv_ei(GLint loc, const float* v) { glUniformMatrix2fv(loc, 1, false, v); }
+inline void glUniformMatrix3fv_ei(GLint loc, const float* v) { glUniformMatrix3fv(loc, 1, false, v); }
+inline void glUniformMatrix4fv_ei(GLint loc, const float* v) { glUniformMatrix4fv(loc, 1, false, v); }
+
+EIGEN_GL_FUNC1_DECLARATION(glUniform, GLint, const)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, float, 2, 2fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, int, 2, 2iv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, float, 3, 3fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, int, 3, 3iv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, float, 4, 4fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, int, 4, 4iv_ei)
+
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 2, 2, Matrix2fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 3, 3, Matrix3fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 4, 4, Matrix4fv_ei)
+
+#endif
+
+#ifdef GL_VERSION_2_1
+
+inline void glUniformMatrix2x3fv_ei(GLint loc, const float* v) { glUniformMatrix2x3fv(loc, 1, false, v); }
+inline void glUniformMatrix3x2fv_ei(GLint loc, const float* v) { glUniformMatrix3x2fv(loc, 1, false, v); }
+inline void glUniformMatrix2x4fv_ei(GLint loc, const float* v) { glUniformMatrix2x4fv(loc, 1, false, v); }
+inline void glUniformMatrix4x2fv_ei(GLint loc, const float* v) { glUniformMatrix4x2fv(loc, 1, false, v); }
+inline void glUniformMatrix3x4fv_ei(GLint loc, const float* v) { glUniformMatrix3x4fv(loc, 1, false, v); }
+inline void glUniformMatrix4x3fv_ei(GLint loc, const float* v) { glUniformMatrix4x3fv(loc, 1, false, v); }
+
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 2, 3, Matrix2x3fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 3, 2, Matrix3x2fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 2, 4, Matrix2x4fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 4, 2, Matrix4x2fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 3, 4, Matrix3x4fv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 4, 3, Matrix4x3fv_ei)
+
+#endif
+
+#ifdef GL_VERSION_3_0
+
+inline void glUniform2uiv_ei(GLint loc, const unsigned int* v) { glUniform2uiv(loc, 1, v); }
+inline void glUniform3uiv_ei(GLint loc, const unsigned int* v) { glUniform3uiv(loc, 1, v); }
+inline void glUniform4uiv_ei(GLint loc, const unsigned int* v) { glUniform4uiv(loc, 1, v); }
+
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, unsigned int, 2, 2uiv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, unsigned int, 3, 3uiv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, unsigned int, 4, 4uiv_ei)
+
+#endif
+
+#ifdef GL_ARB_gpu_shader_fp64
+inline void glUniform2dv_ei(GLint loc, const double* v) { glUniform2dv(loc, 1, v); }
+inline void glUniform3dv_ei(GLint loc, const double* v) { glUniform3dv(loc, 1, v); }
+inline void glUniform4dv_ei(GLint loc, const double* v) { glUniform4dv(loc, 1, v); }
+
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, double, 2, 2dv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, double, 3, 3dv_ei)
+EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, double, 4, 4dv_ei)
+#endif
+
+//@}
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_OPENGL_MODULE_H
diff --git a/contrib/Eigen/Polynomials b/contrib/Eigen/Polynomials
new file mode 100644
index 0000000..a957a95
--- /dev/null
+++ b/contrib/Eigen/Polynomials
@@ -0,0 +1,142 @@
+// 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
+
+#ifndef EIGEN_POLYNOMIALS_MODULE_H
+#define EIGEN_POLYNOMIALS_MODULE_H
+
+#include "../../Eigen/Core"
+
+#include "../../Eigen/Eigenvalues"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
+#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS >= 2)
+#ifndef EIGEN_HIDE_HEAVY_CODE
+#define EIGEN_HIDE_HEAVY_CODE
+#endif
+#elif defined EIGEN_HIDE_HEAVY_CODE
+#undef EIGEN_HIDE_HEAVY_CODE
+#endif
+
+/**
+ * \defgroup Polynomials_Module Polynomials module
+ * \brief This module provides a QR based polynomial solver.
+ *
+ * To use this module, add
+ * \code
+ * #include <contrib/Eigen/Polynomials>
+ * \endcode
+ * at the start of your source file.
+ */
+
+// IWYU pragma: begin_exports
+#include "src/Polynomials/PolynomialUtils.h"
+#include "src/Polynomials/Companion.h"
+#include "src/Polynomials/PolynomialSolver.h"
+// IWYU pragma: end_exports
+
+/**
+        \page polynomials Polynomials defines functions for dealing with polynomials
+        and a QR based polynomial solver.
+        \ingroup Polynomials_Module
+
+        The remainder of the page documents first the functions for evaluating, computing
+        polynomials, computing estimates about polynomials and next the QR based polynomial
+        solver.
+
+        \section polynomialUtils convenient functions to deal with polynomials
+        \subsection roots_to_monicPolynomial
+        The function
+        \code
+        void roots_to_monicPolynomial( const RootVector& rv, Polynomial& poly )
+        \endcode
+        computes the coefficients \f$ a_i \f$ of
+
+        \f$ p(x) = a_0 + a_{1}x + ... + a_{n-1}x^{n-1} + x^n \f$
+
+        where \f$ p \f$ is known through its roots i.e. \f$ p(x) = (x-r_1)(x-r_2)...(x-r_n) \f$.
+
+        \subsection poly_eval
+        The function
+        \code
+        T poly_eval( const Polynomials& poly, const T& x )
+        \endcode
+        evaluates a polynomial at a given point using stabilized H&ouml;rner method.
+
+        The following code: first computes the coefficients in the monomial basis of the monic polynomial that has the
+  provided roots; then, it evaluates the computed polynomial, using a stabilized H&ouml;rner method.
+
+        \include PolynomialUtils1.cpp
+  Output: \verbinclude PolynomialUtils1.out
+
+        \subsection Cauchy bounds
+        The function
+        \code
+        Real cauchy_max_bound( const Polynomial& poly )
+        \endcode
+        provides a maximum bound (the Cauchy one: \f$C(p)\f$) for the absolute value of a root of the given polynomial
+  i.e. \f$ \forall r_i \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$, \f$ |r_i| \le C(p) = \sum_{k=0}^{d} \left |
+  \frac{a_k}{a_d} \right | \f$ The leading coefficient \f$ p \f$: should be non zero \f$a_d \neq 0\f$.
+
+
+        The function
+        \code
+        Real cauchy_min_bound( const Polynomial& poly )
+        \endcode
+        provides a minimum bound (the Cauchy one: \f$c(p)\f$) for the absolute value of a non zero root of the given
+  polynomial i.e. \f$ \forall r_i \neq 0 \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$, \f$ |r_i| \ge c(p) = \left(
+  \sum_{k=0}^{d} \left | \frac{a_k}{a_0} \right | \right)^{-1} \f$
+
+
+
+
+        \section QR polynomial solver class
+        Computes the complex roots of a polynomial by computing the eigenvalues of the associated companion matrix with
+  the QR algorithm.
+
+        The roots of \f$ p(x) = a_0 + a_1 x + a_2 x^2 + a_{3} x^3 + x^4 \f$ are the eigenvalues of
+        \f$
+        \left [
+        \begin{array}{cccc}
+        0 & 0 &  0 & a_0 \\
+        1 & 0 &  0 & a_1 \\
+        0 & 1 &  0 & a_2 \\
+        0 & 0 &  1 & a_3
+        \end{array} \right ]
+        \f$
+
+        However, the QR algorithm is not guaranteed to converge when there are several eigenvalues with same modulus.
+
+        Therefore the current polynomial solver is guaranteed to provide a correct result only when the complex roots
+  \f$r_1,r_2,...,r_d\f$ have distinct moduli i.e.
+
+        \f$ \forall i,j \in [1;d],~ \| r_i \| \neq \| r_j \| \f$.
+
+        With 32bit (float) floating types this problem shows up frequently.
+  However, almost always, correct accuracy is reached even in these cases for 64bit
+  (double) floating types and small polynomial degree (<20).
+
+        \include PolynomialSolver1.cpp
+
+        In the above example:
+
+        -# a simple use of the polynomial solver is shown;
+        -# the accuracy problem with the QR algorithm is presented: a polynomial with almost conjugate roots is provided
+  to the solver. Those roots have almost same module therefore the QR algorithm failed to converge: the accuracy of the
+  last root is bad;
+        -# a simple way to circumvent the problem is shown: use doubles instead of floats.
+
+  Output: \verbinclude PolynomialSolver1.out
+*/
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_POLYNOMIALS_MODULE_H
diff --git a/contrib/Eigen/SparseExtra b/contrib/Eigen/SparseExtra
new file mode 100644
index 0000000..4f9824e
--- /dev/null
+++ b/contrib/Eigen/SparseExtra
@@ -0,0 +1,61 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// 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
+
+#ifndef EIGEN_SPARSE_EXTRA_MODULE_H
+#define EIGEN_SPARSE_EXTRA_MODULE_H
+
+#include "../../Eigen/Sparse"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+#include <vector>
+#include <map>
+#include <unordered_map>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+
+#ifdef EIGEN_GOOGLEHASH_SUPPORT
+#include <google/dense_hash_map>
+#include <google/sparse_hash_map>
+#endif
+
+/**
+ * \defgroup SparseExtra_Module SparseExtra module
+ *
+ * This module contains some experimental features extending the sparse module:
+ * - A RandomSetter which is a wrapper object allowing to set/update a sparse matrix with random access.
+ * - A SparseInverse which calculates a sparse subset of the inverse of a sparse matrix corresponding to nonzeros of the
+ * input
+ * - MatrixMarket format(https://math.nist.gov/MatrixMarket/formats.html) readers and writers for sparse and dense
+ * matrices.
+ *
+ * \code
+ * #include <contrib/Eigen/SparseExtra>
+ * \endcode
+ */
+
+// IWYU pragma: begin_exports
+#include "src/SparseExtra/RandomSetter.h"
+#include "src/SparseExtra/SparseInverse.h"
+
+#include "src/SparseExtra/MarketIO.h"
+
+#if !defined(_WIN32)
+#include <dirent.h>
+#include "src/SparseExtra/MatrixMarketIterator.h"
+#endif
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_SPARSE_EXTRA_MODULE_H
diff --git a/contrib/Eigen/SpecialFunctions b/contrib/Eigen/SpecialFunctions
new file mode 100644
index 0000000..f648cfc
--- /dev/null
+++ b/contrib/Eigen/SpecialFunctions
@@ -0,0 +1,114 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2016 Gael Guennebaud <g.gael@free.fr>
+//
+// 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
+
+#ifndef EIGEN_SPECIALFUNCTIONS_MODULE_H
+#define EIGEN_SPECIALFUNCTIONS_MODULE_H
+
+#include <cmath>
+
+#include "../../Eigen/Core"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+namespace Eigen {
+
+/**
+ * \defgroup SpecialFunctions_Module Special math functions module
+ *
+ * This module features additional coefficient-wise math functions available
+ * within the numext:: namespace for the scalar version, and as method and/or free
+ * functions of Array. Those include:
+ *
+ * - erf
+ * - erfc
+ * - lgamma
+ * - igamma
+ * - igamma_der_a
+ * - gamma_sample_der_alpha
+ * - igammac
+ * - digamma
+ * - ndtri
+ * - polygamma
+ * - zeta
+ * - betainc
+ *
+ * Bessel Functions
+ * - bessel_i0
+ * - bessel_i0e
+ * - bessel_i1
+ * - bessel_i1e
+ * - bessel_j0
+ * - bessel_j1
+ * - bessel_k0
+ * - bessel_k0e
+ * - bessel_k1
+ * - bessel_k1e
+ * - bessel_y0
+ * - bessel_y1
+ *
+ * The implementations are tuned for \c float and \c double, so they do not carry
+ * over to an arbitrary scalar. \c erf and \c erfc accept any other scalar type
+ * that declares its own \c erf / \c erfc in the namespace of that type, where
+ * argument-dependent lookup finds it; a scalar type that declares neither is
+ * rejected at compile time.
+ *
+ * \code
+ * #include <contrib/Eigen/SpecialFunctions>
+ * \endcode
+ */
+//@{
+
+}  // namespace Eigen
+
+// IWYU pragma: begin_exports
+#include "src/SpecialFunctions/BesselFunctionsImpl.h"
+#include "src/SpecialFunctions/BesselFunctionsBFloat16.h"
+#include "src/SpecialFunctions/BesselFunctionsHalf.h"
+#include "src/SpecialFunctions/BesselFunctionsPacketMath.h"
+#include "src/SpecialFunctions/BesselFunctionsFunctors.h"
+#include "src/SpecialFunctions/BesselFunctionsArrayAPI.h"
+#include "src/SpecialFunctions/SpecialFunctionsImpl.h"
+#if defined(EIGEN_HIPCC)
+#include "src/SpecialFunctions/HipVectorCompatibility.h"
+#endif
+#include "src/SpecialFunctions/SpecialFunctionsBFloat16.h"
+#include "src/SpecialFunctions/SpecialFunctionsHalf.h"
+#include "src/SpecialFunctions/SpecialFunctionsPacketMath.h"
+#include "src/SpecialFunctions/SpecialFunctionsFunctors.h"
+#include "src/SpecialFunctions/SpecialFunctionsArrayAPI.h"
+
+#ifndef EIGEN_VECTORIZE_GENERIC
+// TODO(rmlarsen): Make these work with generic vectorization if possible.
+#if defined EIGEN_VECTORIZE_AVX512
+#include "src/SpecialFunctions/arch/AVX/BesselFunctions.h"
+#include "src/SpecialFunctions/arch/AVX/SpecialFunctions.h"
+#include "src/SpecialFunctions/arch/AVX512/BesselFunctions.h"
+#include "src/SpecialFunctions/arch/AVX512/SpecialFunctions.h"
+#elif defined EIGEN_VECTORIZE_AVX
+#include "src/SpecialFunctions/arch/AVX/BesselFunctions.h"
+#include "src/SpecialFunctions/arch/AVX/SpecialFunctions.h"
+#elif defined EIGEN_VECTORIZE_NEON || defined EIGEN_VECTORIZE_SME
+#include "src/SpecialFunctions/arch/NEON/BesselFunctions.h"
+#include "src/SpecialFunctions/arch/NEON/SpecialFunctions.h"
+#endif
+
+#if defined EIGEN_VECTORIZE_GPU
+#include "src/SpecialFunctions/arch/GPU/SpecialFunctions.h"
+#endif
+#endif
+// IWYU pragma: end_exports
+
+namespace Eigen {
+//@}
+}
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_SPECIALFUNCTIONS_MODULE_H
diff --git a/contrib/Eigen/Splines b/contrib/Eigen/Splines
new file mode 100644
index 0000000..c87e805
--- /dev/null
+++ b/contrib/Eigen/Splines
@@ -0,0 +1,39 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010-2011 Hauke Heibel <hauke.heibel@gmail.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
+
+#ifndef EIGEN_SPLINES_MODULE_H
+#define EIGEN_SPLINES_MODULE_H
+
+#include "../../Eigen/Core"
+
+namespace Eigen {
+/**
+ * \defgroup Splines_Module Spline and spline fitting module
+ *
+ * This module provides a simple multi-dimensional spline class while
+ * offering most basic functionality to fit a spline to point sets.
+ *
+ * \code
+ * #include <contrib/Eigen/Splines>
+ * \endcode
+ */
+}
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/Splines/SplineFwd.h"
+#include "src/Splines/Spline.h"
+#include "src/Splines/SplineFitting.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_SPLINES_MODULE_H
diff --git a/contrib/Eigen/StructuredMatrices b/contrib/Eigen/StructuredMatrices
new file mode 100644
index 0000000..3cb6abb
--- /dev/null
+++ b/contrib/Eigen/StructuredMatrices
@@ -0,0 +1,95 @@
+// 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
+
+#ifndef EIGEN_STRUCTURED_MATRICES_MODULE_H
+#define EIGEN_STRUCTURED_MATRICES_MODULE_H
+
+#include "../../Eigen/Core"
+#include "../../Eigen/Eigenvalues"
+#include "../../Eigen/LU"
+#include "../../Eigen/SVD"
+#include "../../Eigen/IterativeLinearSolvers"
+#include "FFT"
+
+namespace Eigen {
+
+/**
+ * \defgroup StructuredMatrices_Module StructuredMatrices module
+ *
+ * This module provides lightweight operator types for displacement-structured
+ * matrices together with fast matrix-vector products and direct solvers:
+ *   - \c Circulant : a circulant matrix, diagonalized by the DFT;
+ *   - \c Toeplitz  : a (possibly rectangular) Toeplitz matrix, multiplied in
+ *     O(n log n) via circulant embedding;
+ *   - \c Hankel    : a (possibly rectangular) Hankel matrix -- a column-reversed
+ *     Toeplitz matrix -- with the same O(n log n) products, and square solves
+ *     through the Toeplitz equivalent;
+ *   - \c KroneckerOperator : the Kronecker product of two dense or diagonal
+ *     matrices as an implicit operator; products, solves, least squares,
+ *     eigendecomposition, SVD, inverse and determinant all factor through the
+ *     operands, and diagonal (in particular identity) factors are stored and
+ *     applied in diagonal form;
+ *   - \c DiagonalPlusLowRank : a diagonal matrix plus a rank-k correction, with
+ *     O(nk) products and O(nk^2) Woodbury solves, closed under inversion;
+ *   - \c Vandermonde : a Vandermonde matrix stored as its nodes, with Horner
+ *     products and O(n^2) Björck-Pereyra primal/dual solves
+ *     (\c BjorckPereyra).
+ *
+ * The operator types derive from \c EigenBase and store only compact generators
+ * or factors. The FFT-backed operators (\c Circulant, \c Toeplitz and \c Hankel)
+ * also keep a precomputed DFT symbol that every product reuses.
+ * The operator types derive from \c EigenBase and store only their generating
+ * vectors; the FFT-backed operators (\c Circulant, \c Toeplitz, \c Bccb) also
+ * keep a precomputed DFT symbol that every product reuses.
+ * Because they expose \c operator* returning an Eigen product expression, they
+ * also plug directly into the matrix-free iterative solvers
+ * (\c ConjugateGradient, \c GMRES, \c MINRES, ...) without forming the dense
+ * matrix; and since they hook into the evaluator system, they can be assigned
+ * to a dense matrix when an explicit representation is needed. Like every
+ * matrix-free operator, they carry no coefficient storage the default
+ * preconditioners could read, so the iterative solvers must be instantiated
+ * with \c IdentityPreconditioner.
+ *
+ * All operator types are closed under transposition (\c transpose(),
+ * \c conjugate(), \c adjoint() return operators of the same kind, the FFT-based
+ * ones reusing the cached symbol), which in particular feeds the least-squares
+ * solvers \c LSMR and \c LeastSquaresConjugateGradient (again with
+ * \c IdentityPreconditioner).
+ * The \c Circulant, \c Toeplitz and \c Hankel operators are closed under
+ * transposition (\c transpose(),
+ * \c conjugate(), \c adjoint() return operators of the same kind, reusing the
+ * cached symbol), which in particular feeds the least-squares solvers \c LSMR
+ * and \c LeastSquaresConjugateGradient (again with \c IdentityPreconditioner).
+ * \c Circulant additionally exposes its closed-form eigendecomposition and SVD
+ * in the Fourier basis, a pseudo-inverse (minimum-norm least-squares) solve,
+ * \c rank(), \c inverse() and \c determinant().
+ *
+ * \code
+ * #include <contrib/Eigen/StructuredMatrices>
+ * \endcode
+ */
+
+}  // namespace Eigen
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "src/StructuredMatrices/StructuredMatrixUtils.h"
+#include "src/StructuredMatrices/Circulant.h"
+#include "src/StructuredMatrices/Toeplitz.h"
+#include "src/StructuredMatrices/LookAheadLevinson.h"
+#include "src/StructuredMatrices/Hankel.h"
+#include "src/StructuredMatrices/KroneckerOperator.h"
+#include "src/StructuredMatrices/DiagonalPlusLowRank.h"
+#include "src/StructuredMatrices/Vandermonde.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_STRUCTURED_MATRICES_MODULE_H
diff --git a/contrib/Eigen/Tensor b/contrib/Eigen/Tensor
new file mode 100644
index 0000000..46d54bd
--- /dev/null
+++ b/contrib/Eigen/Tensor
@@ -0,0 +1,159 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
+// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
+//
+// 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
+
+// A later inclusion can complete a device type after its backend macro is
+// enabled. Backend evaluation still requires the macro before including Eigen.
+#if !defined(EIGEN_TENSOR_MODULE_H) || (defined(EIGEN_USE_THREADS) && !defined(EIGEN_TENSOR_MODULE_THREADS_LOADED)) || \
+    (defined(EIGEN_USE_GPU) && !defined(EIGEN_TENSOR_MODULE_GPU_LOADED)) ||                                            \
+    (defined(EIGEN_USE_SYCL) && !defined(EIGEN_TENSOR_MODULE_SYCL_LOADED))
+#define EIGEN_TENSOR_MODULE_H
+
+// Record caller-provided backend macros before any included header can change
+// them, so later inclusions detect only backends newly enabled by the caller.
+#ifdef EIGEN_USE_THREADS
+#define EIGEN_TENSOR_MODULE_THREADS_LOADED
+#endif
+#ifdef EIGEN_USE_GPU
+#define EIGEN_TENSOR_MODULE_GPU_LOADED
+#endif
+#ifdef EIGEN_USE_SYCL
+#define EIGEN_TENSOR_MODULE_SYCL_LOADED
+#endif
+
+#include "../../Eigen/Core"
+
+#include "SpecialFunctions"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+// IWYU pragma: begin_exports
+#include "../../Eigen/src/Core/util/Meta.h"
+#include "../../Eigen/src/Core/util/MaxSizeVector.h"
+// IWYU pragma: end_exports
+
+/** \defgroup Tensor_Module Tensor Module
+ *
+ * This module provides a Tensor class for storing arbitrarily indexed
+ * objects.
+ *
+ * \code
+ * #include <contrib/Eigen/Tensor>
+ * \endcode
+ *
+ * Much of the documentation can be found \ref eigen_tensors "here".
+ */
+
+#include <atomic>
+#include <chrono>
+#include <cmath>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <thread>
+
+#if defined(EIGEN_USE_THREADS) || defined(EIGEN_USE_SYCL)
+#include "../../Eigen/ThreadPool"
+#endif
+
+#ifdef EIGEN_USE_GPU
+#include <iostream>
+#if defined(EIGEN_USE_HIP)
+#include <hip/hip_runtime.h>
+#else
+#include <cuda_runtime.h>
+#endif
+#endif
+
+// IWYU pragma: begin_exports
+#include "src/Tensor/TensorMacros.h"
+#include "src/Tensor/TensorForwardDeclarations.h"
+#include "src/Tensor/TensorMeta.h"
+#include "src/Tensor/TensorFunctors.h"
+#include "src/Tensor/TensorCostModel.h"
+#include "src/Tensor/TensorDeviceDefault.h"
+#include "src/Tensor/TensorDeviceThreadPool.h"
+#include "src/Tensor/TensorDeviceGpu.h"
+#ifndef gpu_assert
+#define gpu_assert(x)
+#endif
+#include "src/Tensor/TensorDeviceSycl.h"
+#include "src/Tensor/TensorIndexList.h"
+#include "src/Tensor/TensorDimensionList.h"
+#include "src/Tensor/TensorDimensions.h"
+#include "src/Tensor/TensorInitializer.h"
+#include "src/Tensor/TensorTraits.h"
+#include "src/Tensor/TensorRandom.h"
+#include "src/Tensor/TensorUInt128.h"
+#include "src/Tensor/TensorIntDiv.h"
+#include "src/Tensor/TensorGlobalFunctions.h"
+
+#include "src/Tensor/TensorIO.h"
+
+#include "src/Tensor/TensorBase.h"
+#include "src/Tensor/TensorBlock.h"
+
+#include "src/Tensor/TensorEvaluator.h"
+#include "src/Tensor/TensorExpr.h"
+#include "src/Tensor/TensorReduction.h"
+#include "src/Tensor/TensorReductionGpu.h"
+#include "src/Tensor/TensorArgMax.h"
+#include "src/Tensor/TensorConcatenation.h"
+#include "src/Tensor/TensorContractionMapper.h"
+#include "src/Tensor/TensorContractionBlocking.h"
+#include "src/Tensor/TensorContraction.h"
+#include "src/Tensor/TensorContractionThreadPool.h"
+#include "src/Tensor/TensorContractionGpu.h"
+#include "src/Tensor/TensorConversion.h"
+#include "src/Tensor/TensorConvolution.h"
+#include "src/Tensor/TensorFFT.h"
+#include "src/Tensor/TensorPatch.h"
+#include "src/Tensor/TensorImagePatch.h"
+#include "src/Tensor/TensorVolumePatch.h"
+#include "src/Tensor/TensorBroadcasting.h"
+#include "src/Tensor/TensorChipping.h"
+#include "src/Tensor/TensorInflation.h"
+#include "src/Tensor/TensorLayoutSwap.h"
+#include "src/Tensor/TensorMorphing.h"
+#include "src/Tensor/TensorPadding.h"
+#include "src/Tensor/TensorReverse.h"
+#include "src/Tensor/TensorRoll.h"
+#include "src/Tensor/TensorShuffling.h"
+#include "src/Tensor/TensorStriding.h"
+#include "src/Tensor/TensorCustomOp.h"
+#include "src/Tensor/TensorEvalTo.h"
+#include "src/Tensor/TensorForcedEval.h"
+#include "src/Tensor/TensorGenerator.h"
+#include "src/Tensor/TensorAssign.h"
+#include "src/Tensor/TensorScan.h"
+#include "src/Tensor/TensorTrace.h"
+
+#ifdef EIGEN_USE_SYCL
+#include "src/Tensor/TensorReductionSycl.h"
+#include "src/Tensor/TensorConvolutionSycl.h"
+#include "src/Tensor/TensorContractionSycl.h"
+#include "src/Tensor/TensorScanSycl.h"
+#endif
+
+#include "src/Tensor/TensorExecutor.h"
+#include "src/Tensor/TensorDevice.h"
+
+#include "src/Tensor/TensorStorage.h"
+#include "src/Tensor/Tensor.h"
+#include "src/Tensor/TensorFixedSize.h"
+#include "src/Tensor/TensorMap.h"
+#include "src/Tensor/TensorRef.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // Tensor module or newly enabled backend
diff --git a/contrib/Eigen/TensorSymmetry b/contrib/Eigen/TensorSymmetry
new file mode 100644
index 0000000..1b89d6b
--- /dev/null
+++ b/contrib/Eigen/TensorSymmetry
@@ -0,0 +1,39 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
+//
+// 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
+
+#ifndef EIGEN_TENSORSYMMETRY_MODULE_H
+#define EIGEN_TENSORSYMMETRY_MODULE_H
+
+#include "Tensor"
+
+#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
+
+/** \defgroup TensorSymmetry_Module Tensor Symmetry Module
+ *
+ * This module provides a classes that allow for the definition of
+ * symmetries w.r.t. tensor indices.
+ *
+ * Including this module will implicitly include the Tensor module.
+ *
+ * \code
+ * #include <contrib/Eigen/TensorSymmetry>
+ * \endcode
+ */
+
+// IWYU pragma: begin_exports
+#include "src/TensorSymmetry/util/TemplateGroupTheory.h"
+#include "src/TensorSymmetry/Symmetry.h"
+#include "src/TensorSymmetry/StaticSymmetry.h"
+#include "src/TensorSymmetry/DynamicSymmetry.h"
+// IWYU pragma: end_exports
+
+#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
+
+#endif  // EIGEN_TENSORSYMMETRY_MODULE_H
diff --git a/unsupported/Eigen/src/ArpackSupport/ArpackSelfAdjointEigenSolver.h b/contrib/Eigen/src/ArpackSupport/ArpackSelfAdjointEigenSolver.h
similarity index 100%
rename from unsupported/Eigen/src/ArpackSupport/ArpackSelfAdjointEigenSolver.h
rename to contrib/Eigen/src/ArpackSupport/ArpackSelfAdjointEigenSolver.h
diff --git a/contrib/Eigen/src/ArpackSupport/InternalHeaderCheck.h b/contrib/Eigen/src/ArpackSupport/InternalHeaderCheck.h
new file mode 100644
index 0000000..a686dc1
--- /dev/null
+++ b/contrib/Eigen/src/ArpackSupport/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_ARPACKSUPPORT_MODULE_H
+#error "Please include contrib/Eigen/ArpackSupport instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h b/contrib/Eigen/src/AutoDiff/AutoDiffJacobian.h
similarity index 100%
rename from unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h
rename to contrib/Eigen/src/AutoDiff/AutoDiffJacobian.h
diff --git a/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h b/contrib/Eigen/src/AutoDiff/AutoDiffScalar.h
similarity index 100%
rename from unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h
rename to contrib/Eigen/src/AutoDiff/AutoDiffScalar.h
diff --git a/unsupported/Eigen/src/AutoDiff/CoherentPadOp.h b/contrib/Eigen/src/AutoDiff/CoherentPadOp.h
similarity index 100%
rename from unsupported/Eigen/src/AutoDiff/CoherentPadOp.h
rename to contrib/Eigen/src/AutoDiff/CoherentPadOp.h
diff --git a/contrib/Eigen/src/AutoDiff/InternalHeaderCheck.h b/contrib/Eigen/src/AutoDiff/InternalHeaderCheck.h
new file mode 100644
index 0000000..dc6c873
--- /dev/null
+++ b/contrib/Eigen/src/AutoDiff/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_AUTODIFF_MODULE_H
+#error "Please include contrib/Eigen/AutoDiff instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/BVH/BVAlgorithms.h b/contrib/Eigen/src/BVH/BVAlgorithms.h
similarity index 100%
rename from unsupported/Eigen/src/BVH/BVAlgorithms.h
rename to contrib/Eigen/src/BVH/BVAlgorithms.h
diff --git a/contrib/Eigen/src/BVH/InternalHeaderCheck.h b/contrib/Eigen/src/BVH/InternalHeaderCheck.h
new file mode 100644
index 0000000..8b68259
--- /dev/null
+++ b/contrib/Eigen/src/BVH/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_BVH_MODULE_H
+#error "Please include contrib/Eigen/BVH instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/BVH/KdBVH.h b/contrib/Eigen/src/BVH/KdBVH.h
similarity index 100%
rename from unsupported/Eigen/src/BVH/KdBVH.h
rename to contrib/Eigen/src/BVH/KdBVH.h
diff --git a/unsupported/Eigen/src/EulerAngles/CMakeLists.txt b/contrib/Eigen/src/EulerAngles/CMakeLists.txt
similarity index 69%
rename from unsupported/Eigen/src/EulerAngles/CMakeLists.txt
rename to contrib/Eigen/src/EulerAngles/CMakeLists.txt
index 61423c7..a40ac07 100644
--- a/unsupported/Eigen/src/EulerAngles/CMakeLists.txt
+++ b/contrib/Eigen/src/EulerAngles/CMakeLists.txt
@@ -6,6 +6,6 @@
 if(EIGEN_INSTALL)
   install(FILES
     ${Eigen_EulerAngles_SRCS}
-    DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen/src/EulerAngles COMPONENT Devel
+    DESTINATION ${INCLUDE_INSTALL_DIR}/contrib/Eigen/src/EulerAngles COMPONENT Devel
     )
 endif()
diff --git a/unsupported/Eigen/src/EulerAngles/EulerAngles.h b/contrib/Eigen/src/EulerAngles/EulerAngles.h
similarity index 100%
rename from unsupported/Eigen/src/EulerAngles/EulerAngles.h
rename to contrib/Eigen/src/EulerAngles/EulerAngles.h
diff --git a/unsupported/Eigen/src/EulerAngles/EulerSystem.h b/contrib/Eigen/src/EulerAngles/EulerSystem.h
similarity index 100%
rename from unsupported/Eigen/src/EulerAngles/EulerSystem.h
rename to contrib/Eigen/src/EulerAngles/EulerSystem.h
diff --git a/contrib/Eigen/src/EulerAngles/InternalHeaderCheck.h b/contrib/Eigen/src/EulerAngles/InternalHeaderCheck.h
new file mode 100644
index 0000000..2073995
--- /dev/null
+++ b/contrib/Eigen/src/EulerAngles/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_EULERANGLES_MODULE_H
+#error "Please include contrib/Eigen/EulerAngles instead of including headers inside the src directory directly."
+#endif
diff --git a/contrib/Eigen/src/FFT/InternalHeaderCheck.h b/contrib/Eigen/src/FFT/InternalHeaderCheck.h
new file mode 100644
index 0000000..71a632d
--- /dev/null
+++ b/contrib/Eigen/src/FFT/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_FFT_MODULE_H
+#error "Please include contrib/Eigen/FFT instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/FFT/duccfft_impl.h b/contrib/Eigen/src/FFT/duccfft_impl.h
similarity index 100%
rename from unsupported/Eigen/src/FFT/duccfft_impl.h
rename to contrib/Eigen/src/FFT/duccfft_impl.h
diff --git a/unsupported/Eigen/src/FFT/fftw_impl.h b/contrib/Eigen/src/FFT/fftw_impl.h
similarity index 100%
rename from unsupported/Eigen/src/FFT/fftw_impl.h
rename to contrib/Eigen/src/FFT/fftw_impl.h
diff --git a/unsupported/Eigen/src/FFT/imklfft_impl.h b/contrib/Eigen/src/FFT/imklfft_impl.h
similarity index 100%
rename from unsupported/Eigen/src/FFT/imklfft_impl.h
rename to contrib/Eigen/src/FFT/imklfft_impl.h
diff --git a/unsupported/Eigen/src/FFT/kissfft_impl.h b/contrib/Eigen/src/FFT/kissfft_impl.h
similarity index 100%
rename from unsupported/Eigen/src/FFT/kissfft_impl.h
rename to contrib/Eigen/src/FFT/kissfft_impl.h
diff --git a/unsupported/Eigen/src/FFT/pocketfft_impl.h b/contrib/Eigen/src/FFT/pocketfft_impl.h
similarity index 100%
rename from unsupported/Eigen/src/FFT/pocketfft_impl.h
rename to contrib/Eigen/src/FFT/pocketfft_impl.h
diff --git a/unsupported/Eigen/src/GPU/CuBlasSupport.h b/contrib/Eigen/src/GPU/CuBlasSupport.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/CuBlasSupport.h
rename to contrib/Eigen/src/GPU/CuBlasSupport.h
diff --git a/unsupported/Eigen/src/GPU/CuDssSupport.h b/contrib/Eigen/src/GPU/CuDssSupport.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/CuDssSupport.h
rename to contrib/Eigen/src/GPU/CuDssSupport.h
diff --git a/unsupported/Eigen/src/GPU/CuFftSupport.h b/contrib/Eigen/src/GPU/CuFftSupport.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/CuFftSupport.h
rename to contrib/Eigen/src/GPU/CuFftSupport.h
diff --git a/unsupported/Eigen/src/GPU/CuSolverSupport.h b/contrib/Eigen/src/GPU/CuSolverSupport.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/CuSolverSupport.h
rename to contrib/Eigen/src/GPU/CuSolverSupport.h
diff --git a/unsupported/Eigen/src/GPU/CuSparseSupport.h b/contrib/Eigen/src/GPU/CuSparseSupport.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/CuSparseSupport.h
rename to contrib/Eigen/src/GPU/CuSparseSupport.h
diff --git a/unsupported/Eigen/src/GPU/DeviceBlasExpr.h b/contrib/Eigen/src/GPU/DeviceBlasExpr.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceBlasExpr.h
rename to contrib/Eigen/src/GPU/DeviceBlasExpr.h
diff --git a/unsupported/Eigen/src/GPU/DeviceDispatch.h b/contrib/Eigen/src/GPU/DeviceDispatch.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceDispatch.h
rename to contrib/Eigen/src/GPU/DeviceDispatch.h
diff --git a/unsupported/Eigen/src/GPU/DeviceExpr.h b/contrib/Eigen/src/GPU/DeviceExpr.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceExpr.h
rename to contrib/Eigen/src/GPU/DeviceExpr.h
diff --git a/unsupported/Eigen/src/GPU/DeviceMatrix.h b/contrib/Eigen/src/GPU/DeviceMatrix.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceMatrix.h
rename to contrib/Eigen/src/GPU/DeviceMatrix.h
diff --git a/unsupported/Eigen/src/GPU/DeviceScalar.h b/contrib/Eigen/src/GPU/DeviceScalar.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceScalar.h
rename to contrib/Eigen/src/GPU/DeviceScalar.h
diff --git a/unsupported/Eigen/src/GPU/DeviceScalarOps.h b/contrib/Eigen/src/GPU/DeviceScalarOps.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceScalarOps.h
rename to contrib/Eigen/src/GPU/DeviceScalarOps.h
diff --git a/unsupported/Eigen/src/GPU/DeviceSolverExpr.h b/contrib/Eigen/src/GPU/DeviceSolverExpr.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/DeviceSolverExpr.h
rename to contrib/Eigen/src/GPU/DeviceSolverExpr.h
diff --git a/unsupported/Eigen/src/GPU/FwdDecl.h b/contrib/Eigen/src/GPU/FwdDecl.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/FwdDecl.h
rename to contrib/Eigen/src/GPU/FwdDecl.h
diff --git a/unsupported/Eigen/src/GPU/GpuContext.h b/contrib/Eigen/src/GPU/GpuContext.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuContext.h
rename to contrib/Eigen/src/GPU/GpuContext.h
diff --git a/unsupported/Eigen/src/GPU/GpuEigenSolver.h b/contrib/Eigen/src/GPU/GpuEigenSolver.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuEigenSolver.h
rename to contrib/Eigen/src/GPU/GpuEigenSolver.h
diff --git a/unsupported/Eigen/src/GPU/GpuFFT.h b/contrib/Eigen/src/GPU/GpuFFT.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuFFT.h
rename to contrib/Eigen/src/GPU/GpuFFT.h
diff --git a/unsupported/Eigen/src/GPU/GpuLLT.h b/contrib/Eigen/src/GPU/GpuLLT.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuLLT.h
rename to contrib/Eigen/src/GPU/GpuLLT.h
diff --git a/unsupported/Eigen/src/GPU/GpuLU.h b/contrib/Eigen/src/GPU/GpuLU.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuLU.h
rename to contrib/Eigen/src/GPU/GpuLU.h
diff --git a/unsupported/Eigen/src/GPU/GpuQR.h b/contrib/Eigen/src/GPU/GpuQR.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuQR.h
rename to contrib/Eigen/src/GPU/GpuQR.h
diff --git a/unsupported/Eigen/src/GPU/GpuSVD.h b/contrib/Eigen/src/GPU/GpuSVD.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSVD.h
rename to contrib/Eigen/src/GPU/GpuSVD.h
diff --git a/unsupported/Eigen/src/GPU/GpuSolverContext.h b/contrib/Eigen/src/GPU/GpuSolverContext.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSolverContext.h
rename to contrib/Eigen/src/GPU/GpuSolverContext.h
diff --git a/unsupported/Eigen/src/GPU/GpuSparseContext.h b/contrib/Eigen/src/GPU/GpuSparseContext.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSparseContext.h
rename to contrib/Eigen/src/GPU/GpuSparseContext.h
diff --git a/unsupported/Eigen/src/GPU/GpuSparseLDLT.h b/contrib/Eigen/src/GPU/GpuSparseLDLT.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSparseLDLT.h
rename to contrib/Eigen/src/GPU/GpuSparseLDLT.h
diff --git a/unsupported/Eigen/src/GPU/GpuSparseLLT.h b/contrib/Eigen/src/GPU/GpuSparseLLT.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSparseLLT.h
rename to contrib/Eigen/src/GPU/GpuSparseLLT.h
diff --git a/unsupported/Eigen/src/GPU/GpuSparseLU.h b/contrib/Eigen/src/GPU/GpuSparseLU.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSparseLU.h
rename to contrib/Eigen/src/GPU/GpuSparseLU.h
diff --git a/unsupported/Eigen/src/GPU/GpuSparseSolverBase.h b/contrib/Eigen/src/GPU/GpuSparseSolverBase.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSparseSolverBase.h
rename to contrib/Eigen/src/GPU/GpuSparseSolverBase.h
diff --git a/unsupported/Eigen/src/GPU/GpuSupport.h b/contrib/Eigen/src/GPU/GpuSupport.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/GpuSupport.h
rename to contrib/Eigen/src/GPU/GpuSupport.h
diff --git a/contrib/Eigen/src/GPU/InternalHeaderCheck.h b/contrib/Eigen/src/GPU/InternalHeaderCheck.h
new file mode 100644
index 0000000..d0f7eef
--- /dev/null
+++ b/contrib/Eigen/src/GPU/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_GPU_MODULE_H
+#error "Please include contrib/Eigen/GPU instead of including headers inside the src/GPU directory directly."
+#endif
diff --git a/unsupported/Eigen/src/GPU/Meta.h b/contrib/Eigen/src/GPU/Meta.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/Meta.h
rename to contrib/Eigen/src/GPU/Meta.h
diff --git a/unsupported/Eigen/src/GPU/README.md b/contrib/Eigen/src/GPU/README.md
similarity index 98%
rename from unsupported/Eigen/src/GPU/README.md
rename to contrib/Eigen/src/GPU/README.md
index 8e6421b..548c5c3 100644
--- a/unsupported/Eigen/src/GPU/README.md
+++ b/contrib/Eigen/src/GPU/README.md
@@ -1,4 +1,4 @@
-# Eigen GPU Module (`unsupported/Eigen/GPU`)
+# Eigen GPU Module (`contrib/Eigen/GPU`)
 
 GPU-accelerated linear algebra for Eigen users, dispatching to NVIDIA CUDA
 Math Libraries (cuBLAS, cuSOLVER, cuFFT, cuSPARSE, cuDSS). Requires CUDA 11.4+;
@@ -34,7 +34,7 @@
 [COLMAP](https://github.com/colmap/colmap/issues/4018) have open requests for
 GPU-accelerated sparse solvers, and third-party projects like
 [cholespy](https://github.com/rgl-epfl/cholespy) exist specifically because
-Eigen lacks them. The `unsupported/Eigen/GPU` module provides GPU sparse Cholesky, LDL^T,
+Eigen lacks them. The `contrib/Eigen/GPU` module provides GPU sparse Cholesky, LDL^T,
 and LU factorization via cuDSS, alongside dense solvers (cuSOLVER), matrix
 products (cuBLAS), FFT (cuFFT), and sparse matrix-vector products (cuSPARSE).
 
@@ -56,9 +56,9 @@
 Eigen. Here is a side-by-side comparison:
 
 ```cpp
-// ---- CPU (Eigen) ----               // ---- GPU (unsupported/Eigen/GPU) ----
+// ---- CPU (Eigen) ----               // ---- GPU (contrib/Eigen/GPU) ----
 #include <Eigen/Dense>                  #define EIGEN_USE_GPU
-                                        #include <unsupported/Eigen/GPU>
+                                        #include <contrib/Eigen/GPU>
 
 // Dense
 MatrixXd A = ...;                       auto d_A = gpu::DeviceMatrix<double>::fromHost(A);
@@ -80,7 +80,7 @@
 plain literals (`2 * d_A`, `d_A / 2`, `-d_A`), and unsupported expressions are
 compile errors.
 
-**Standalone module.** `unsupported/Eigen/GPU` does not modify or depend on Eigen's Core
+**Standalone module.** `contrib/Eigen/GPU` does not modify or depend on Eigen's Core
 expression template system (`MatrixBase`, `CwiseBinaryOp`, etc.).
 `DeviceMatrix` is not an Eigen expression type and does not inherit from
 `MatrixBase`. The expression layer is a thin compile-time dispatch where every
@@ -223,7 +223,7 @@
 cuBLAS is required by `DeviceMatrix` itself (every `Context` creates a cuBLAS
 handle eagerly) and is also a runtime dependency of cuDSS, so it is the one
 constant. cuDSS additionally requires `EIGEN_CUDSS` to be defined before
-including `unsupported/Eigen/GPU`.
+including `contrib/Eigen/GPU`.
 
 ## Usage
 
@@ -384,7 +384,7 @@
 
 Requires [cuDSS](https://docs.nvidia.com/cuda/cudss/) (separate install, CUDA
 12.0+), which is distributed outside the CUDA Toolkit and versioned separately
-from it. Define `EIGEN_CUDSS` before including `unsupported/Eigen/GPU`; see
+from it. Define `EIGEN_CUDSS` before including `contrib/Eigen/GPU`; see
 [Linking](#eigen_gpu_linking) for link flags.
 
 ```cpp
@@ -466,7 +466,7 @@
 Plans and data layouts are [cuFFT](https://docs.nvidia.com/cuda/cufft/)'s. The
 scaling convention is not: cuFFT leaves its transforms unnormalized, and
 `gpu::FFT` applies the 1/n on the inverse so that `inv(fwd(x)) == x`, matching
-`unsupported/Eigen/FFT`.
+`contrib/Eigen/FFT`.
 
 ```cpp
 gpu::FFT<float> fft;                // shares stream + cuBLAS with the
@@ -1178,7 +1178,7 @@
 - **cuTENSOR for Tensor module.** Replace the hand-written GPU tensor
   contraction and reduction kernels (~2300 lines in
   `TensorContractionGpu.h` / `TensorReductionGpu.h`) with cuTENSOR dispatch,
-  following the same library-dispatch pattern used by `unsupported/Eigen/GPU`.
+  following the same library-dispatch pattern used by `contrib/Eigen/GPU`.
 - **Unified/zero-copy memory for Jetson.** Use `cudaMallocManaged` or
   `cudaHostAllocMapped` to eliminate `fromHost()` / `toHost()` copies on
   integrated GPUs (Jetson) where CPU and GPU share DRAM.
diff --git a/unsupported/Eigen/src/GPU/type_traits.h b/contrib/Eigen/src/GPU/type_traits.h
similarity index 100%
rename from unsupported/Eigen/src/GPU/type_traits.h
rename to contrib/Eigen/src/GPU/type_traits.h
diff --git a/contrib/Eigen/src/KroneckerProduct/InternalHeaderCheck.h b/contrib/Eigen/src/KroneckerProduct/InternalHeaderCheck.h
new file mode 100644
index 0000000..07be5c2
--- /dev/null
+++ b/contrib/Eigen/src/KroneckerProduct/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_KRONECKER_PRODUCT_MODULE_H
+#error "Please include contrib/Eigen/KroneckerProduct instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h b/contrib/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h
similarity index 100%
rename from unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h
rename to contrib/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt b/contrib/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt
similarity index 100%
rename from unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt
rename to contrib/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt
diff --git a/contrib/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h b/contrib/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h
new file mode 100644
index 0000000..751871f
--- /dev/null
+++ b/contrib/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_LEVENBERGMARQUARDT_MODULE_H
+#error "Please include contrib/Eigen/LevenbergMarquardt instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h b/contrib/Eigen/src/LevenbergMarquardt/LMcovar.h
similarity index 100%
rename from unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h
rename to contrib/Eigen/src/LevenbergMarquardt/LMcovar.h
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h b/contrib/Eigen/src/LevenbergMarquardt/LMonestep.h
similarity index 100%
rename from unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h
rename to contrib/Eigen/src/LevenbergMarquardt/LMonestep.h
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h b/contrib/Eigen/src/LevenbergMarquardt/LMpar.h
similarity index 100%
rename from unsupported/Eigen/src/LevenbergMarquardt/LMpar.h
rename to contrib/Eigen/src/LevenbergMarquardt/LMpar.h
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h b/contrib/Eigen/src/LevenbergMarquardt/LMqrsolv.h
similarity index 100%
rename from unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h
rename to contrib/Eigen/src/LevenbergMarquardt/LMqrsolv.h
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h b/contrib/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h
similarity index 100%
rename from unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h
rename to contrib/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h
diff --git a/contrib/Eigen/src/MatrixFunctions/InternalHeaderCheck.h b/contrib/Eigen/src/MatrixFunctions/InternalHeaderCheck.h
new file mode 100644
index 0000000..99cbbb0
--- /dev/null
+++ b/contrib/Eigen/src/MatrixFunctions/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_MATRIX_FUNCTIONS_MODULE_H
+#error "Please include contrib/Eigen/MatrixFunctions instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h b/contrib/Eigen/src/MatrixFunctions/MatrixExponential.h
similarity index 100%
rename from unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h
rename to contrib/Eigen/src/MatrixFunctions/MatrixExponential.h
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h b/contrib/Eigen/src/MatrixFunctions/MatrixFunction.h
similarity index 100%
rename from unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h
rename to contrib/Eigen/src/MatrixFunctions/MatrixFunction.h
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h b/contrib/Eigen/src/MatrixFunctions/MatrixLogarithm.h
similarity index 100%
rename from unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h
rename to contrib/Eigen/src/MatrixFunctions/MatrixLogarithm.h
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h b/contrib/Eigen/src/MatrixFunctions/MatrixPower.h
similarity index 100%
rename from unsupported/Eigen/src/MatrixFunctions/MatrixPower.h
rename to contrib/Eigen/src/MatrixFunctions/MatrixPower.h
diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h b/contrib/Eigen/src/MatrixFunctions/MatrixSquareRoot.h
similarity index 100%
rename from unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h
rename to contrib/Eigen/src/MatrixFunctions/MatrixSquareRoot.h
diff --git a/unsupported/Eigen/src/MatrixFunctions/StemFunction.h b/contrib/Eigen/src/MatrixFunctions/StemFunction.h
similarity index 100%
rename from unsupported/Eigen/src/MatrixFunctions/StemFunction.h
rename to contrib/Eigen/src/MatrixFunctions/StemFunction.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h b/contrib/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h
rename to contrib/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h
diff --git a/contrib/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h b/contrib/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h
new file mode 100644
index 0000000..74d102a
--- /dev/null
+++ b/contrib/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h
@@ -0,0 +1,7 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_NONLINEAROPTIMIZATION_MODULE_H
+#error \
+    "Please include contrib/Eigen/NonLinearOptimization instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h b/contrib/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h
rename to contrib/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/chkder.h b/contrib/Eigen/src/NonLinearOptimization/chkder.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/chkder.h
rename to contrib/Eigen/src/NonLinearOptimization/chkder.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/covar.h b/contrib/Eigen/src/NonLinearOptimization/covar.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/covar.h
rename to contrib/Eigen/src/NonLinearOptimization/covar.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/dogleg.h b/contrib/Eigen/src/NonLinearOptimization/dogleg.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/dogleg.h
rename to contrib/Eigen/src/NonLinearOptimization/dogleg.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h b/contrib/Eigen/src/NonLinearOptimization/fdjac1.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/fdjac1.h
rename to contrib/Eigen/src/NonLinearOptimization/fdjac1.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/lmpar.h b/contrib/Eigen/src/NonLinearOptimization/lmpar.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/lmpar.h
rename to contrib/Eigen/src/NonLinearOptimization/lmpar.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h b/contrib/Eigen/src/NonLinearOptimization/qrsolv.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/qrsolv.h
rename to contrib/Eigen/src/NonLinearOptimization/qrsolv.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/r1mpyq.h b/contrib/Eigen/src/NonLinearOptimization/r1mpyq.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/r1mpyq.h
rename to contrib/Eigen/src/NonLinearOptimization/r1mpyq.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/r1updt.h b/contrib/Eigen/src/NonLinearOptimization/r1updt.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/r1updt.h
rename to contrib/Eigen/src/NonLinearOptimization/r1updt.h
diff --git a/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h b/contrib/Eigen/src/NonLinearOptimization/rwupdt.h
similarity index 100%
rename from unsupported/Eigen/src/NonLinearOptimization/rwupdt.h
rename to contrib/Eigen/src/NonLinearOptimization/rwupdt.h
diff --git a/contrib/Eigen/src/NumericalDiff/InternalHeaderCheck.h b/contrib/Eigen/src/NumericalDiff/InternalHeaderCheck.h
new file mode 100644
index 0000000..5bc2a81
--- /dev/null
+++ b/contrib/Eigen/src/NumericalDiff/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_NUMERICALDIFF_MODULE_H
+#error "Please include contrib/Eigen/NumericalDiff instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h b/contrib/Eigen/src/NumericalDiff/NumericalDiff.h
similarity index 100%
rename from unsupported/Eigen/src/NumericalDiff/NumericalDiff.h
rename to contrib/Eigen/src/NumericalDiff/NumericalDiff.h
diff --git a/unsupported/Eigen/src/Polynomials/Companion.h b/contrib/Eigen/src/Polynomials/Companion.h
similarity index 100%
rename from unsupported/Eigen/src/Polynomials/Companion.h
rename to contrib/Eigen/src/Polynomials/Companion.h
diff --git a/contrib/Eigen/src/Polynomials/InternalHeaderCheck.h b/contrib/Eigen/src/Polynomials/InternalHeaderCheck.h
new file mode 100644
index 0000000..9892c48
--- /dev/null
+++ b/contrib/Eigen/src/Polynomials/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_POLYNOMIALS_MODULE_H
+#error "Please include contrib/Eigen/Polynomials instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/Polynomials/PolynomialSolver.h b/contrib/Eigen/src/Polynomials/PolynomialSolver.h
similarity index 99%
rename from unsupported/Eigen/src/Polynomials/PolynomialSolver.h
rename to contrib/Eigen/src/Polynomials/PolynomialSolver.h
index 9298c18..c8d7da9 100644
--- a/unsupported/Eigen/src/Polynomials/PolynomialSolver.h
+++ b/contrib/Eigen/src/Polynomials/PolynomialSolver.h
@@ -286,7 +286,7 @@
  * - real roots with greatest, smallest absolute real value.
  * - greatest, smallest real roots.
  *
- * WARNING: this polynomial solver is experimental, part of the unsupported Eigen modules.
+ * WARNING: this polynomial solver is experimental, part of the contrib Eigen modules.
  *
  *
  * Currently a QR algorithm is used to compute the eigenvalues of the companion matrix of
diff --git a/unsupported/Eigen/src/Polynomials/PolynomialUtils.h b/contrib/Eigen/src/Polynomials/PolynomialUtils.h
similarity index 100%
rename from unsupported/Eigen/src/Polynomials/PolynomialUtils.h
rename to contrib/Eigen/src/Polynomials/PolynomialUtils.h
diff --git a/contrib/Eigen/src/SparseExtra/InternalHeaderCheck.h b/contrib/Eigen/src/SparseExtra/InternalHeaderCheck.h
new file mode 100644
index 0000000..b36f9d8
--- /dev/null
+++ b/contrib/Eigen/src/SparseExtra/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_SPARSE_EXTRA_MODULE_H
+#error "Please include contrib/Eigen/SparseExtra instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/SparseExtra/MarketIO.h b/contrib/Eigen/src/SparseExtra/MarketIO.h
similarity index 100%
rename from unsupported/Eigen/src/SparseExtra/MarketIO.h
rename to contrib/Eigen/src/SparseExtra/MarketIO.h
diff --git a/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h b/contrib/Eigen/src/SparseExtra/MatrixMarketIterator.h
similarity index 100%
rename from unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h
rename to contrib/Eigen/src/SparseExtra/MatrixMarketIterator.h
diff --git a/unsupported/Eigen/src/SparseExtra/RandomSetter.h b/contrib/Eigen/src/SparseExtra/RandomSetter.h
similarity index 100%
rename from unsupported/Eigen/src/SparseExtra/RandomSetter.h
rename to contrib/Eigen/src/SparseExtra/RandomSetter.h
diff --git a/unsupported/Eigen/src/SparseExtra/SparseInverse.h b/contrib/Eigen/src/SparseExtra/SparseInverse.h
similarity index 100%
rename from unsupported/Eigen/src/SparseExtra/SparseInverse.h
rename to contrib/Eigen/src/SparseExtra/SparseInverse.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsArrayAPI.h b/contrib/Eigen/src/SpecialFunctions/BesselFunctionsArrayAPI.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/BesselFunctionsArrayAPI.h
rename to contrib/Eigen/src/SpecialFunctions/BesselFunctionsArrayAPI.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsBFloat16.h b/contrib/Eigen/src/SpecialFunctions/BesselFunctionsBFloat16.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/BesselFunctionsBFloat16.h
rename to contrib/Eigen/src/SpecialFunctions/BesselFunctionsBFloat16.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsFunctors.h b/contrib/Eigen/src/SpecialFunctions/BesselFunctionsFunctors.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/BesselFunctionsFunctors.h
rename to contrib/Eigen/src/SpecialFunctions/BesselFunctionsFunctors.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsHalf.h b/contrib/Eigen/src/SpecialFunctions/BesselFunctionsHalf.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/BesselFunctionsHalf.h
rename to contrib/Eigen/src/SpecialFunctions/BesselFunctionsHalf.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsImpl.h b/contrib/Eigen/src/SpecialFunctions/BesselFunctionsImpl.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/BesselFunctionsImpl.h
rename to contrib/Eigen/src/SpecialFunctions/BesselFunctionsImpl.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/BesselFunctionsPacketMath.h b/contrib/Eigen/src/SpecialFunctions/BesselFunctionsPacketMath.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/BesselFunctionsPacketMath.h
rename to contrib/Eigen/src/SpecialFunctions/BesselFunctionsPacketMath.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/HipVectorCompatibility.h b/contrib/Eigen/src/SpecialFunctions/HipVectorCompatibility.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/HipVectorCompatibility.h
rename to contrib/Eigen/src/SpecialFunctions/HipVectorCompatibility.h
diff --git a/contrib/Eigen/src/SpecialFunctions/InternalHeaderCheck.h b/contrib/Eigen/src/SpecialFunctions/InternalHeaderCheck.h
new file mode 100644
index 0000000..cf263d2
--- /dev/null
+++ b/contrib/Eigen/src/SpecialFunctions/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_SPECIALFUNCTIONS_MODULE_H
+#error "Please include contrib/Eigen/SpecialFunctions instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h b/contrib/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h
rename to contrib/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsBFloat16.h b/contrib/Eigen/src/SpecialFunctions/SpecialFunctionsBFloat16.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsBFloat16.h
rename to contrib/Eigen/src/SpecialFunctions/SpecialFunctionsBFloat16.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h b/contrib/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h
rename to contrib/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h b/contrib/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h
rename to contrib/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h b/contrib/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h
rename to contrib/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h b/contrib/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h
rename to contrib/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/AVX/BesselFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/AVX/BesselFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/AVX/BesselFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/AVX/BesselFunctions.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/AVX/SpecialFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/AVX/SpecialFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/AVX/SpecialFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/AVX/SpecialFunctions.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/AVX512/BesselFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/AVX512/BesselFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/AVX512/BesselFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/AVX512/BesselFunctions.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/AVX512/SpecialFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/AVX512/SpecialFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/AVX512/SpecialFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/AVX512/SpecialFunctions.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/GPU/SpecialFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/GPU/SpecialFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/GPU/SpecialFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/GPU/SpecialFunctions.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/NEON/BesselFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/NEON/BesselFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/NEON/BesselFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/NEON/BesselFunctions.h
diff --git a/unsupported/Eigen/src/SpecialFunctions/arch/NEON/SpecialFunctions.h b/contrib/Eigen/src/SpecialFunctions/arch/NEON/SpecialFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/SpecialFunctions/arch/NEON/SpecialFunctions.h
rename to contrib/Eigen/src/SpecialFunctions/arch/NEON/SpecialFunctions.h
diff --git a/contrib/Eigen/src/Splines/InternalHeaderCheck.h b/contrib/Eigen/src/Splines/InternalHeaderCheck.h
new file mode 100644
index 0000000..c2cc28c
--- /dev/null
+++ b/contrib/Eigen/src/Splines/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_SPLINES_MODULE_H
+#error "Please include contrib/Eigen/Splines instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/Splines/Spline.h b/contrib/Eigen/src/Splines/Spline.h
similarity index 100%
rename from unsupported/Eigen/src/Splines/Spline.h
rename to contrib/Eigen/src/Splines/Spline.h
diff --git a/unsupported/Eigen/src/Splines/SplineFitting.h b/contrib/Eigen/src/Splines/SplineFitting.h
similarity index 100%
rename from unsupported/Eigen/src/Splines/SplineFitting.h
rename to contrib/Eigen/src/Splines/SplineFitting.h
diff --git a/unsupported/Eigen/src/Splines/SplineFwd.h b/contrib/Eigen/src/Splines/SplineFwd.h
similarity index 100%
rename from unsupported/Eigen/src/Splines/SplineFwd.h
rename to contrib/Eigen/src/Splines/SplineFwd.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/Circulant.h b/contrib/Eigen/src/StructuredMatrices/Circulant.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/Circulant.h
rename to contrib/Eigen/src/StructuredMatrices/Circulant.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/DiagonalPlusLowRank.h b/contrib/Eigen/src/StructuredMatrices/DiagonalPlusLowRank.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/DiagonalPlusLowRank.h
rename to contrib/Eigen/src/StructuredMatrices/DiagonalPlusLowRank.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/Hankel.h b/contrib/Eigen/src/StructuredMatrices/Hankel.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/Hankel.h
rename to contrib/Eigen/src/StructuredMatrices/Hankel.h
diff --git a/contrib/Eigen/src/StructuredMatrices/InternalHeaderCheck.h b/contrib/Eigen/src/StructuredMatrices/InternalHeaderCheck.h
new file mode 100644
index 0000000..038f608
--- /dev/null
+++ b/contrib/Eigen/src/StructuredMatrices/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_STRUCTURED_MATRICES_MODULE_H
+#error "Please include contrib/Eigen/StructuredMatrices instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/StructuredMatrices/KroneckerOperator.h b/contrib/Eigen/src/StructuredMatrices/KroneckerOperator.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/KroneckerOperator.h
rename to contrib/Eigen/src/StructuredMatrices/KroneckerOperator.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/LookAheadLevinson.h b/contrib/Eigen/src/StructuredMatrices/LookAheadLevinson.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/LookAheadLevinson.h
rename to contrib/Eigen/src/StructuredMatrices/LookAheadLevinson.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/StructuredMatrixUtils.h b/contrib/Eigen/src/StructuredMatrices/StructuredMatrixUtils.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/StructuredMatrixUtils.h
rename to contrib/Eigen/src/StructuredMatrices/StructuredMatrixUtils.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/Toeplitz.h b/contrib/Eigen/src/StructuredMatrices/Toeplitz.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/Toeplitz.h
rename to contrib/Eigen/src/StructuredMatrices/Toeplitz.h
diff --git a/unsupported/Eigen/src/StructuredMatrices/Vandermonde.h b/contrib/Eigen/src/StructuredMatrices/Vandermonde.h
similarity index 100%
rename from unsupported/Eigen/src/StructuredMatrices/Vandermonde.h
rename to contrib/Eigen/src/StructuredMatrices/Vandermonde.h
diff --git a/contrib/Eigen/src/Tensor/InternalHeaderCheck.h b/contrib/Eigen/src/Tensor/InternalHeaderCheck.h
new file mode 100644
index 0000000..c26c8f6
--- /dev/null
+++ b/contrib/Eigen/src/Tensor/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_TENSOR_MODULE_H
+#error "Please include contrib/Eigen/Tensor instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/Tensor/README.md b/contrib/Eigen/src/Tensor/README.md
similarity index 99%
rename from unsupported/Eigen/src/Tensor/README.md
rename to contrib/Eigen/src/Tensor/README.md
index 20e27e9..0d1163f 100644
--- a/unsupported/Eigen/src/Tensor/README.md
+++ b/contrib/Eigen/src/Tensor/README.md
@@ -3,19 +3,19 @@
 Tensors are multidimensional arrays of elements. Elements are typically scalars,
 but more complex types such as strings are also supported.
 
-The Tensor module is part of Eigen's unsupported modules. While it is actively
+The Tensor module is part of Eigen's contrib modules. While it is actively
 used in production (e.g. in TensorFlow), its API may change without notice.
 
 To use the Tensor module, include the following header:
 
 ```cpp
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 ```
 
 ## Quick Start
 
 ```cpp
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 #include <iostream>
 
 int main() {
@@ -531,7 +531,7 @@
 
 ```cpp
 #define EIGEN_USE_THREADS
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 // Create the Eigen ThreadPool.
 Eigen::ThreadPool pool(8 /* number of threads in pool */);
@@ -553,7 +553,7 @@
 
 ```cpp
 #define EIGEN_USE_GPU
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 // Allocate data on GPU.
 float* d_a;
@@ -1214,7 +1214,7 @@
 
 ### Special Math Functions
 
-These require including `<unsupported/Eigen/SpecialFunctions>` in addition to
+These require including `<contrib/Eigen/SpecialFunctions>` in addition to
 the Tensor header.
 
 ### (Operation) lgamma()
diff --git a/unsupported/Eigen/src/Tensor/Tensor.h b/contrib/Eigen/src/Tensor/Tensor.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/Tensor.h
rename to contrib/Eigen/src/Tensor/Tensor.h
diff --git a/unsupported/Eigen/src/Tensor/TensorArgMax.h b/contrib/Eigen/src/Tensor/TensorArgMax.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorArgMax.h
rename to contrib/Eigen/src/Tensor/TensorArgMax.h
diff --git a/unsupported/Eigen/src/Tensor/TensorAssign.h b/contrib/Eigen/src/Tensor/TensorAssign.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorAssign.h
rename to contrib/Eigen/src/Tensor/TensorAssign.h
diff --git a/unsupported/Eigen/src/Tensor/TensorBase.h b/contrib/Eigen/src/Tensor/TensorBase.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorBase.h
rename to contrib/Eigen/src/Tensor/TensorBase.h
diff --git a/unsupported/Eigen/src/Tensor/TensorBlock.h b/contrib/Eigen/src/Tensor/TensorBlock.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorBlock.h
rename to contrib/Eigen/src/Tensor/TensorBlock.h
diff --git a/unsupported/Eigen/src/Tensor/TensorBroadcasting.h b/contrib/Eigen/src/Tensor/TensorBroadcasting.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorBroadcasting.h
rename to contrib/Eigen/src/Tensor/TensorBroadcasting.h
diff --git a/unsupported/Eigen/src/Tensor/TensorChipping.h b/contrib/Eigen/src/Tensor/TensorChipping.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorChipping.h
rename to contrib/Eigen/src/Tensor/TensorChipping.h
diff --git a/unsupported/Eigen/src/Tensor/TensorConcatenation.h b/contrib/Eigen/src/Tensor/TensorConcatenation.h
similarity index 99%
rename from unsupported/Eigen/src/Tensor/TensorConcatenation.h
rename to contrib/Eigen/src/Tensor/TensorConcatenation.h
index b618b7e..4792647 100644
--- a/unsupported/Eigen/src/Tensor/TensorConcatenation.h
+++ b/contrib/Eigen/src/Tensor/TensorConcatenation.h
@@ -129,7 +129,7 @@
                         YOU_MADE_A_PROGRAMMING_MISTAKE);
     // TensorConcatenationOp requires both operands to have the same static
     // rank. Reshape the lower-rank operand explicitly if you need to mix
-    // ranks; see the concatenate() entry in unsupported/Eigen/src/Tensor/README.md.
+    // ranks; see the concatenate() entry in contrib/Eigen/src/Tensor/README.md.
     EIGEN_STATIC_ASSERT((NumDims == RightNumDims), YOU_MADE_A_PROGRAMMING_MISTAKE);
     EIGEN_STATIC_ASSERT((NumDims > 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
 
diff --git a/unsupported/Eigen/src/Tensor/TensorContraction.h b/contrib/Eigen/src/Tensor/TensorContraction.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorContraction.h
rename to contrib/Eigen/src/Tensor/TensorContraction.h
diff --git a/unsupported/Eigen/src/Tensor/TensorContractionBlocking.h b/contrib/Eigen/src/Tensor/TensorContractionBlocking.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorContractionBlocking.h
rename to contrib/Eigen/src/Tensor/TensorContractionBlocking.h
diff --git a/unsupported/Eigen/src/Tensor/TensorContractionCuda.h b/contrib/Eigen/src/Tensor/TensorContractionCuda.h
similarity index 69%
rename from unsupported/Eigen/src/Tensor/TensorContractionCuda.h
rename to contrib/Eigen/src/Tensor/TensorContractionCuda.h
index bf8117e..c61d8a5 100644
--- a/unsupported/Eigen/src/Tensor/TensorContractionCuda.h
+++ b/contrib/Eigen/src/Tensor/TensorContractionCuda.h
@@ -6,7 +6,7 @@
 
 #if defined(__clang__) || defined(__GNUC__)
 #warning \
-    "Deprecated header file, please either include the main unsupported/Eigen/Tensor header or the respective TensorContractionGpu.h file"
+    "Deprecated header file, please either include the main contrib/Eigen/Tensor header or the respective TensorContractionGpu.h file"
 #endif
 
 #include "TensorContractionGpu.h"
diff --git a/unsupported/Eigen/src/Tensor/TensorContractionGpu.h b/contrib/Eigen/src/Tensor/TensorContractionGpu.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorContractionGpu.h
rename to contrib/Eigen/src/Tensor/TensorContractionGpu.h
diff --git a/unsupported/Eigen/src/Tensor/TensorContractionMapper.h b/contrib/Eigen/src/Tensor/TensorContractionMapper.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorContractionMapper.h
rename to contrib/Eigen/src/Tensor/TensorContractionMapper.h
diff --git a/unsupported/Eigen/src/Tensor/TensorContractionSycl.h b/contrib/Eigen/src/Tensor/TensorContractionSycl.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorContractionSycl.h
rename to contrib/Eigen/src/Tensor/TensorContractionSycl.h
diff --git a/unsupported/Eigen/src/Tensor/TensorContractionThreadPool.h b/contrib/Eigen/src/Tensor/TensorContractionThreadPool.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorContractionThreadPool.h
rename to contrib/Eigen/src/Tensor/TensorContractionThreadPool.h
diff --git a/unsupported/Eigen/src/Tensor/TensorConversion.h b/contrib/Eigen/src/Tensor/TensorConversion.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorConversion.h
rename to contrib/Eigen/src/Tensor/TensorConversion.h
diff --git a/unsupported/Eigen/src/Tensor/TensorConvolution.h b/contrib/Eigen/src/Tensor/TensorConvolution.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorConvolution.h
rename to contrib/Eigen/src/Tensor/TensorConvolution.h
diff --git a/unsupported/Eigen/src/Tensor/TensorConvolutionSycl.h b/contrib/Eigen/src/Tensor/TensorConvolutionSycl.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorConvolutionSycl.h
rename to contrib/Eigen/src/Tensor/TensorConvolutionSycl.h
diff --git a/unsupported/Eigen/src/Tensor/TensorCostModel.h b/contrib/Eigen/src/Tensor/TensorCostModel.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorCostModel.h
rename to contrib/Eigen/src/Tensor/TensorCostModel.h
diff --git a/unsupported/Eigen/src/Tensor/TensorCustomOp.h b/contrib/Eigen/src/Tensor/TensorCustomOp.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorCustomOp.h
rename to contrib/Eigen/src/Tensor/TensorCustomOp.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDevice.h b/contrib/Eigen/src/Tensor/TensorDevice.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDevice.h
rename to contrib/Eigen/src/Tensor/TensorDevice.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDeviceCuda.h b/contrib/Eigen/src/Tensor/TensorDeviceCuda.h
similarity index 69%
rename from unsupported/Eigen/src/Tensor/TensorDeviceCuda.h
rename to contrib/Eigen/src/Tensor/TensorDeviceCuda.h
index f1d986a..dcfa5eb 100644
--- a/unsupported/Eigen/src/Tensor/TensorDeviceCuda.h
+++ b/contrib/Eigen/src/Tensor/TensorDeviceCuda.h
@@ -6,7 +6,7 @@
 
 #if defined(__clang__) || defined(__GNUC__)
 #warning \
-    "Deprecated header file, please either include the main unsupported/Eigen/Tensor header or the respective TensorDeviceGpu.h file"
+    "Deprecated header file, please either include the main contrib/Eigen/Tensor header or the respective TensorDeviceGpu.h file"
 #endif
 
 #include "TensorDeviceGpu.h"
diff --git a/unsupported/Eigen/src/Tensor/TensorDeviceDefault.h b/contrib/Eigen/src/Tensor/TensorDeviceDefault.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDeviceDefault.h
rename to contrib/Eigen/src/Tensor/TensorDeviceDefault.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDeviceGpu.h b/contrib/Eigen/src/Tensor/TensorDeviceGpu.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDeviceGpu.h
rename to contrib/Eigen/src/Tensor/TensorDeviceGpu.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDeviceSycl.h b/contrib/Eigen/src/Tensor/TensorDeviceSycl.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDeviceSycl.h
rename to contrib/Eigen/src/Tensor/TensorDeviceSycl.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDeviceThreadPool.h b/contrib/Eigen/src/Tensor/TensorDeviceThreadPool.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDeviceThreadPool.h
rename to contrib/Eigen/src/Tensor/TensorDeviceThreadPool.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDimensionList.h b/contrib/Eigen/src/Tensor/TensorDimensionList.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDimensionList.h
rename to contrib/Eigen/src/Tensor/TensorDimensionList.h
diff --git a/unsupported/Eigen/src/Tensor/TensorDimensions.h b/contrib/Eigen/src/Tensor/TensorDimensions.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorDimensions.h
rename to contrib/Eigen/src/Tensor/TensorDimensions.h
diff --git a/unsupported/Eigen/src/Tensor/TensorEvalTo.h b/contrib/Eigen/src/Tensor/TensorEvalTo.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorEvalTo.h
rename to contrib/Eigen/src/Tensor/TensorEvalTo.h
diff --git a/unsupported/Eigen/src/Tensor/TensorEvaluator.h b/contrib/Eigen/src/Tensor/TensorEvaluator.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorEvaluator.h
rename to contrib/Eigen/src/Tensor/TensorEvaluator.h
diff --git a/unsupported/Eigen/src/Tensor/TensorExecutor.h b/contrib/Eigen/src/Tensor/TensorExecutor.h
similarity index 99%
rename from unsupported/Eigen/src/Tensor/TensorExecutor.h
rename to contrib/Eigen/src/Tensor/TensorExecutor.h
index 67b97a7..6aec270 100644
--- a/unsupported/Eigen/src/Tensor/TensorExecutor.h
+++ b/contrib/Eigen/src/Tensor/TensorExecutor.h
@@ -39,7 +39,7 @@
  public:
   typedef typename Expression::Index StorageIndex;
 
-  // Including `unsupported/Eigen/Tensor` in different translation units
+  // Including `contrib/Eigen/Tensor` in different translation units
   // with/without `EIGEN_USE_THREADS` or `EIGEN_USE_GPU` is a potential ODR
   // violation. If this template is instantiated with a non-default device, it
   // means that this header file was included without defining
diff --git a/unsupported/Eigen/src/Tensor/TensorExpr.h b/contrib/Eigen/src/Tensor/TensorExpr.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorExpr.h
rename to contrib/Eigen/src/Tensor/TensorExpr.h
diff --git a/unsupported/Eigen/src/Tensor/TensorFFT.h b/contrib/Eigen/src/Tensor/TensorFFT.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorFFT.h
rename to contrib/Eigen/src/Tensor/TensorFFT.h
diff --git a/unsupported/Eigen/src/Tensor/TensorFixedSize.h b/contrib/Eigen/src/Tensor/TensorFixedSize.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorFixedSize.h
rename to contrib/Eigen/src/Tensor/TensorFixedSize.h
diff --git a/unsupported/Eigen/src/Tensor/TensorForcedEval.h b/contrib/Eigen/src/Tensor/TensorForcedEval.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorForcedEval.h
rename to contrib/Eigen/src/Tensor/TensorForcedEval.h
diff --git a/unsupported/Eigen/src/Tensor/TensorForwardDeclarations.h b/contrib/Eigen/src/Tensor/TensorForwardDeclarations.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorForwardDeclarations.h
rename to contrib/Eigen/src/Tensor/TensorForwardDeclarations.h
diff --git a/unsupported/Eigen/src/Tensor/TensorFunctors.h b/contrib/Eigen/src/Tensor/TensorFunctors.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorFunctors.h
rename to contrib/Eigen/src/Tensor/TensorFunctors.h
diff --git a/unsupported/Eigen/src/Tensor/TensorGenerator.h b/contrib/Eigen/src/Tensor/TensorGenerator.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorGenerator.h
rename to contrib/Eigen/src/Tensor/TensorGenerator.h
diff --git a/unsupported/Eigen/src/Tensor/TensorGlobalFunctions.h b/contrib/Eigen/src/Tensor/TensorGlobalFunctions.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorGlobalFunctions.h
rename to contrib/Eigen/src/Tensor/TensorGlobalFunctions.h
diff --git a/unsupported/Eigen/src/Tensor/TensorIO.h b/contrib/Eigen/src/Tensor/TensorIO.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorIO.h
rename to contrib/Eigen/src/Tensor/TensorIO.h
diff --git a/unsupported/Eigen/src/Tensor/TensorImagePatch.h b/contrib/Eigen/src/Tensor/TensorImagePatch.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorImagePatch.h
rename to contrib/Eigen/src/Tensor/TensorImagePatch.h
diff --git a/unsupported/Eigen/src/Tensor/TensorIndexList.h b/contrib/Eigen/src/Tensor/TensorIndexList.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorIndexList.h
rename to contrib/Eigen/src/Tensor/TensorIndexList.h
diff --git a/unsupported/Eigen/src/Tensor/TensorInflation.h b/contrib/Eigen/src/Tensor/TensorInflation.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorInflation.h
rename to contrib/Eigen/src/Tensor/TensorInflation.h
diff --git a/unsupported/Eigen/src/Tensor/TensorInitializer.h b/contrib/Eigen/src/Tensor/TensorInitializer.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorInitializer.h
rename to contrib/Eigen/src/Tensor/TensorInitializer.h
diff --git a/unsupported/Eigen/src/Tensor/TensorIntDiv.h b/contrib/Eigen/src/Tensor/TensorIntDiv.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorIntDiv.h
rename to contrib/Eigen/src/Tensor/TensorIntDiv.h
diff --git a/unsupported/Eigen/src/Tensor/TensorLayoutSwap.h b/contrib/Eigen/src/Tensor/TensorLayoutSwap.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorLayoutSwap.h
rename to contrib/Eigen/src/Tensor/TensorLayoutSwap.h
diff --git a/unsupported/Eigen/src/Tensor/TensorMacros.h b/contrib/Eigen/src/Tensor/TensorMacros.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorMacros.h
rename to contrib/Eigen/src/Tensor/TensorMacros.h
diff --git a/unsupported/Eigen/src/Tensor/TensorMap.h b/contrib/Eigen/src/Tensor/TensorMap.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorMap.h
rename to contrib/Eigen/src/Tensor/TensorMap.h
diff --git a/unsupported/Eigen/src/Tensor/TensorMeta.h b/contrib/Eigen/src/Tensor/TensorMeta.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorMeta.h
rename to contrib/Eigen/src/Tensor/TensorMeta.h
diff --git a/unsupported/Eigen/src/Tensor/TensorMorphing.h b/contrib/Eigen/src/Tensor/TensorMorphing.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorMorphing.h
rename to contrib/Eigen/src/Tensor/TensorMorphing.h
diff --git a/unsupported/Eigen/src/Tensor/TensorPadding.h b/contrib/Eigen/src/Tensor/TensorPadding.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorPadding.h
rename to contrib/Eigen/src/Tensor/TensorPadding.h
diff --git a/unsupported/Eigen/src/Tensor/TensorPatch.h b/contrib/Eigen/src/Tensor/TensorPatch.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorPatch.h
rename to contrib/Eigen/src/Tensor/TensorPatch.h
diff --git a/unsupported/Eigen/src/Tensor/TensorRandom.h b/contrib/Eigen/src/Tensor/TensorRandom.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorRandom.h
rename to contrib/Eigen/src/Tensor/TensorRandom.h
diff --git a/unsupported/Eigen/src/Tensor/TensorReduction.h b/contrib/Eigen/src/Tensor/TensorReduction.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorReduction.h
rename to contrib/Eigen/src/Tensor/TensorReduction.h
diff --git a/unsupported/Eigen/src/Tensor/TensorReductionGpu.h b/contrib/Eigen/src/Tensor/TensorReductionGpu.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorReductionGpu.h
rename to contrib/Eigen/src/Tensor/TensorReductionGpu.h
diff --git a/unsupported/Eigen/src/Tensor/TensorReductionSycl.h b/contrib/Eigen/src/Tensor/TensorReductionSycl.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorReductionSycl.h
rename to contrib/Eigen/src/Tensor/TensorReductionSycl.h
diff --git a/unsupported/Eigen/src/Tensor/TensorRef.h b/contrib/Eigen/src/Tensor/TensorRef.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorRef.h
rename to contrib/Eigen/src/Tensor/TensorRef.h
diff --git a/unsupported/Eigen/src/Tensor/TensorReverse.h b/contrib/Eigen/src/Tensor/TensorReverse.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorReverse.h
rename to contrib/Eigen/src/Tensor/TensorReverse.h
diff --git a/unsupported/Eigen/src/Tensor/TensorRoll.h b/contrib/Eigen/src/Tensor/TensorRoll.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorRoll.h
rename to contrib/Eigen/src/Tensor/TensorRoll.h
diff --git a/unsupported/Eigen/src/Tensor/TensorScan.h b/contrib/Eigen/src/Tensor/TensorScan.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorScan.h
rename to contrib/Eigen/src/Tensor/TensorScan.h
diff --git a/unsupported/Eigen/src/Tensor/TensorScanSycl.h b/contrib/Eigen/src/Tensor/TensorScanSycl.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorScanSycl.h
rename to contrib/Eigen/src/Tensor/TensorScanSycl.h
diff --git a/unsupported/Eigen/src/Tensor/TensorShuffling.h b/contrib/Eigen/src/Tensor/TensorShuffling.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorShuffling.h
rename to contrib/Eigen/src/Tensor/TensorShuffling.h
diff --git a/unsupported/Eigen/src/Tensor/TensorStorage.h b/contrib/Eigen/src/Tensor/TensorStorage.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorStorage.h
rename to contrib/Eigen/src/Tensor/TensorStorage.h
diff --git a/unsupported/Eigen/src/Tensor/TensorStriding.h b/contrib/Eigen/src/Tensor/TensorStriding.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorStriding.h
rename to contrib/Eigen/src/Tensor/TensorStriding.h
diff --git a/unsupported/Eigen/src/Tensor/TensorTrace.h b/contrib/Eigen/src/Tensor/TensorTrace.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorTrace.h
rename to contrib/Eigen/src/Tensor/TensorTrace.h
diff --git a/unsupported/Eigen/src/Tensor/TensorTraits.h b/contrib/Eigen/src/Tensor/TensorTraits.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorTraits.h
rename to contrib/Eigen/src/Tensor/TensorTraits.h
diff --git a/unsupported/Eigen/src/Tensor/TensorUInt128.h b/contrib/Eigen/src/Tensor/TensorUInt128.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorUInt128.h
rename to contrib/Eigen/src/Tensor/TensorUInt128.h
diff --git a/unsupported/Eigen/src/Tensor/TensorVolumePatch.h b/contrib/Eigen/src/Tensor/TensorVolumePatch.h
similarity index 100%
rename from unsupported/Eigen/src/Tensor/TensorVolumePatch.h
rename to contrib/Eigen/src/Tensor/TensorVolumePatch.h
diff --git a/unsupported/Eigen/src/TensorSymmetry/DynamicSymmetry.h b/contrib/Eigen/src/TensorSymmetry/DynamicSymmetry.h
similarity index 100%
rename from unsupported/Eigen/src/TensorSymmetry/DynamicSymmetry.h
rename to contrib/Eigen/src/TensorSymmetry/DynamicSymmetry.h
diff --git a/contrib/Eigen/src/TensorSymmetry/InternalHeaderCheck.h b/contrib/Eigen/src/TensorSymmetry/InternalHeaderCheck.h
new file mode 100644
index 0000000..547afdc
--- /dev/null
+++ b/contrib/Eigen/src/TensorSymmetry/InternalHeaderCheck.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: The Eigen Authors
+// SPDX-License-Identifier: MPL-2.0
+
+#ifndef EIGEN_TENSORSYMMETRY_MODULE_H
+#error "Please include contrib/Eigen/TensorSymmetry instead of including headers inside the src directory directly."
+#endif
diff --git a/unsupported/Eigen/src/TensorSymmetry/StaticSymmetry.h b/contrib/Eigen/src/TensorSymmetry/StaticSymmetry.h
similarity index 100%
rename from unsupported/Eigen/src/TensorSymmetry/StaticSymmetry.h
rename to contrib/Eigen/src/TensorSymmetry/StaticSymmetry.h
diff --git a/unsupported/Eigen/src/TensorSymmetry/Symmetry.h b/contrib/Eigen/src/TensorSymmetry/Symmetry.h
similarity index 100%
rename from unsupported/Eigen/src/TensorSymmetry/Symmetry.h
rename to contrib/Eigen/src/TensorSymmetry/Symmetry.h
diff --git a/unsupported/Eigen/src/TensorSymmetry/util/TemplateGroupTheory.h b/contrib/Eigen/src/TensorSymmetry/util/TemplateGroupTheory.h
similarity index 100%
rename from unsupported/Eigen/src/TensorSymmetry/util/TemplateGroupTheory.h
rename to contrib/Eigen/src/TensorSymmetry/util/TemplateGroupTheory.h
diff --git a/contrib/README.txt b/contrib/README.txt
new file mode 100644
index 0000000..f19488a
--- /dev/null
+++ b/contrib/README.txt
@@ -0,0 +1,57 @@
+This directory hosts modules that satisfy a looser API-stability contract
+than the rest of Eigen. Most of the content here is mature and widely
+depended on (Tensor, AutoDiff, FFT, MatrixFunctions, Polynomials, Splines,
+NNLS, the GPU host-dispatch layer, ...), but the interfaces may evolve
+between minor releases and a small subset is genuinely experimental.
+
+Up to and including Eigen 4.x this directory was named "unsupported/".
+The tree was renamed to "contrib/" in Eigen 5.x; legacy
+<unsupported/Eigen/...> include paths continue to work via forwarding
+header shims under ../unsupported/.
+
+In order to use a contrib module either:
+
+ - add path_to_eigen/contrib to your include path and do:
+   #include <Eigen/ModuleHeader>
+
+ - or directly:
+   #include <contrib/Eigen/ModuleHeader>
+
+
+If you are interested in contributing to one of them, or have other stuff
+you would like to share, feel free to contact us via the upstream project
+on GitLab: https://gitlab.com/libeigen/eigen.
+
+Any kind of contributions are much appreciated, even very preliminary ones.
+However, it:
+ - must rely on Eigen,
+ - must be highly related to math,
+ - should have some general purpose in the sense that it could
+   potentially become a core Eigen module (or be merged into another one).
+
+In doubt feel free to contact us. For instance, if your addon is very
+specific but shows an interesting way of using Eigen, it could make for a
+nice demo.
+
+
+This directory is organized as follow:
+
+contrib/Eigen/ModuleHeader1
+contrib/Eigen/ModuleHeader2
+contrib/Eigen/...
+contrib/Eigen/src/Module1/SourceFile1.h
+contrib/Eigen/src/Module1/SourceFile2.h
+contrib/Eigen/src/Module1/...
+contrib/Eigen/src/Module2/SourceFile1.h
+contrib/Eigen/src/Module2/SourceFile2.h
+contrib/Eigen/src/Module2/...
+contrib/Eigen/src/...
+contrib/doc/snippets/.cpp   <- code snippets for the doc
+contrib/doc/examples/.cpp   <- examples for the doc
+contrib/doc/TutorialModule1.dox
+contrib/doc/TutorialModule2.dox
+contrib/doc/...
+contrib/test/.cpp           <- unit test files
+
+The documentation is generated at the same time as the main Eigen
+documentation. The .html files are generated in: build_dir/doc/html/contrib/
diff --git a/unsupported/benchmarks/AutoDiff/CMakeLists.txt b/contrib/benchmarks/AutoDiff/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/AutoDiff/CMakeLists.txt
rename to contrib/benchmarks/AutoDiff/CMakeLists.txt
diff --git a/unsupported/benchmarks/AutoDiff/bench_autodiff.cpp b/contrib/benchmarks/AutoDiff/bench_autodiff.cpp
similarity index 98%
rename from unsupported/benchmarks/AutoDiff/bench_autodiff.cpp
rename to contrib/benchmarks/AutoDiff/bench_autodiff.cpp
index a77be78..651acd1 100644
--- a/unsupported/benchmarks/AutoDiff/bench_autodiff.cpp
+++ b/contrib/benchmarks/AutoDiff/bench_autodiff.cpp
@@ -5,8 +5,8 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/AutoDiff>
-#include <unsupported/Eigen/NumericalDiff>
+#include <contrib/Eigen/AutoDiff>
+#include <contrib/Eigen/NumericalDiff>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/CMakeLists.txt b/contrib/benchmarks/CMakeLists.txt
similarity index 92%
rename from unsupported/benchmarks/CMakeLists.txt
rename to contrib/benchmarks/CMakeLists.txt
index 5e8100d..669e824 100644
--- a/unsupported/benchmarks/CMakeLists.txt
+++ b/contrib/benchmarks/CMakeLists.txt
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier: MPL-2.0
 
 cmake_minimum_required(VERSION 3.10)
-project(EigenUnsupportedBenchmarks CXX)
+project(EigenContribBenchmarks CXX)
 
 find_package(benchmark REQUIRED)
 find_package(Threads REQUIRED)
@@ -38,7 +38,7 @@
 add_subdirectory(StructuredMatrices)
 
 # GPU benchmarks have their own CMake project (needs CUDAToolkit).
-# They can also be built standalone: cmake -B build -S unsupported/benchmarks/GPU
+# They can also be built standalone: cmake -B build -S contrib/benchmarks/GPU
 find_package(CUDAToolkit QUIET)
 if(CUDAToolkit_FOUND)
   add_subdirectory(GPU)
diff --git a/unsupported/benchmarks/GPU/CMakeLists.txt b/contrib/benchmarks/GPU/CMakeLists.txt
similarity index 98%
rename from unsupported/benchmarks/GPU/CMakeLists.txt
rename to contrib/benchmarks/GPU/CMakeLists.txt
index 1736482..b53c2a4 100644
--- a/unsupported/benchmarks/GPU/CMakeLists.txt
+++ b/contrib/benchmarks/GPU/CMakeLists.txt
@@ -2,7 +2,7 @@
 # Build separately from the main benchmark tree since they need CUDA toolchain.
 #
 # Usage:
-#   cmake -G Ninja -B build-bench-gpu -S unsupported/benchmarks/GPU \
+#   cmake -G Ninja -B build-bench-gpu -S contrib/benchmarks/GPU \
 #         -DCMAKE_CUDA_ARCHITECTURES=89
 #   cmake --build build-bench-gpu
 #
diff --git a/unsupported/benchmarks/GPU/ba_results.md b/contrib/benchmarks/GPU/ba_results.md
similarity index 98%
rename from unsupported/benchmarks/GPU/ba_results.md
rename to contrib/benchmarks/GPU/ba_results.md
index b02fb30..826dc46 100644
--- a/unsupported/benchmarks/GPU/ba_results.md
+++ b/contrib/benchmarks/GPU/ba_results.md
@@ -136,7 +136,7 @@
 
 ```bash
 # Build
-cmake -G Ninja -B build-bench-gpu -S unsupported/benchmarks/GPU -DCMAKE_CUDA_ARCHITECTURES=89
+cmake -G Ninja -B build-bench-gpu -S contrib/benchmarks/GPU -DCMAKE_CUDA_ARCHITECTURES=89
 cmake --build build-bench-gpu --target bench_ba
 
 # Download BAL datasets
diff --git a/unsupported/benchmarks/GPU/bench_ba.cu b/contrib/benchmarks/GPU/bench_ba.cu
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_ba.cu
rename to contrib/benchmarks/GPU/bench_ba.cu
index c19d64c..1c82580 100644
--- a/unsupported/benchmarks/GPU/bench_ba.cu
+++ b/contrib/benchmarks/GPU/bench_ba.cu
@@ -29,7 +29,7 @@
 
 #include <Eigen/Sparse>
 #include <Eigen/IterativeLinearSolvers>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include <cmath>
 #include <cstdio>
diff --git a/unsupported/benchmarks/GPU/bench_batching.cpp b/contrib/benchmarks/GPU/bench_batching.cpp
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_batching.cpp
rename to contrib/benchmarks/GPU/bench_batching.cpp
index 7d75f2a..233d70c 100644
--- a/unsupported/benchmarks/GPU/bench_batching.cpp
+++ b/contrib/benchmarks/GPU/bench_batching.cpp
@@ -19,7 +19,7 @@
 #include <benchmark/benchmark.h>
 
 #include <Eigen/Cholesky>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include <memory>
 #include <vector>
diff --git a/unsupported/benchmarks/GPU/bench_cg_sync.cu b/contrib/benchmarks/GPU/bench_cg_sync.cu
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_cg_sync.cu
rename to contrib/benchmarks/GPU/bench_cg_sync.cu
index 0c6cd7a..3eba481 100644
--- a/unsupported/benchmarks/GPU/bench_cg_sync.cu
+++ b/contrib/benchmarks/GPU/bench_cg_sync.cu
@@ -16,7 +16,7 @@
 #include <benchmark/benchmark.h>
 
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include <cusparse.h>
 
 using namespace Eigen;
diff --git a/unsupported/benchmarks/GPU/bench_cg_vs_cpu.cu b/contrib/benchmarks/GPU/bench_cg_vs_cpu.cu
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_cg_vs_cpu.cu
rename to contrib/benchmarks/GPU/bench_cg_vs_cpu.cu
index a403584..ea94211 100644
--- a/unsupported/benchmarks/GPU/bench_cg_vs_cpu.cu
+++ b/contrib/benchmarks/GPU/bench_cg_vs_cpu.cu
@@ -13,7 +13,7 @@
 
 #include <Eigen/Sparse>
 #include <Eigen/IterativeLinearSolvers>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/GPU/bench_chaining.cpp b/contrib/benchmarks/GPU/bench_chaining.cpp
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_chaining.cpp
rename to contrib/benchmarks/GPU/bench_chaining.cpp
index b877dc2..1a47df7 100644
--- a/unsupported/benchmarks/GPU/bench_chaining.cpp
+++ b/contrib/benchmarks/GPU/bench_chaining.cpp
@@ -15,7 +15,7 @@
 #include <benchmark/benchmark.h>
 
 #include <Eigen/Cholesky>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/GPU/bench_fft.cpp b/contrib/benchmarks/GPU/bench_fft.cpp
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_fft.cpp
rename to contrib/benchmarks/GPU/bench_fft.cpp
index 61a8142..e1cfd26 100644
--- a/unsupported/benchmarks/GPU/bench_fft.cpp
+++ b/contrib/benchmarks/GPU/bench_fft.cpp
@@ -15,7 +15,7 @@
 
 #include <benchmark/benchmark.h>
 
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/GPU/bench_gemm.cpp b/contrib/benchmarks/GPU/bench_gemm.cpp
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_gemm.cpp
rename to contrib/benchmarks/GPU/bench_gemm.cpp
index 1a65aff..87aa974 100644
--- a/unsupported/benchmarks/GPU/bench_gemm.cpp
+++ b/contrib/benchmarks/GPU/bench_gemm.cpp
@@ -15,7 +15,7 @@
 #include <benchmark/benchmark.h>
 
 // EIGEN_USE_GPU is set by the CMake target (eigen_add_gpu_benchmark).
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/GPU/bench_overhead.cpp b/contrib/benchmarks/GPU/bench_overhead.cpp
similarity index 98%
rename from unsupported/benchmarks/GPU/bench_overhead.cpp
rename to contrib/benchmarks/GPU/bench_overhead.cpp
index fb827fa..b5d42ba 100644
--- a/unsupported/benchmarks/GPU/bench_overhead.cpp
+++ b/contrib/benchmarks/GPU/bench_overhead.cpp
@@ -22,7 +22,7 @@
 //   SmallBuffer* / PoolAllocFree — small DeviceBuffer round trip (idle, behind in-flight work) and the pool itself
 //
 // Build (standalone project, see CMakeLists.txt in this directory):
-//   cmake -G Ninja -B build-bench-gpu -S unsupported/benchmarks/GPU \
+//   cmake -G Ninja -B build-bench-gpu -S contrib/benchmarks/GPU \
 //         -DCMAKE_CUDA_ARCHITECTURES=89
 //   cmake --build build-bench-gpu --target bench_overhead
 //   ./build-bench-gpu/bench_overhead
@@ -32,7 +32,7 @@
 #endif
 #include <Eigen/Cholesky>
 #include <Eigen/SparseCore>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include <benchmark/benchmark.h>
 #include <cuda_runtime.h>
diff --git a/unsupported/benchmarks/GPU/bench_solvers.cpp b/contrib/benchmarks/GPU/bench_solvers.cpp
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_solvers.cpp
rename to contrib/benchmarks/GPU/bench_solvers.cpp
index c036275..014b5f7 100644
--- a/unsupported/benchmarks/GPU/bench_solvers.cpp
+++ b/contrib/benchmarks/GPU/bench_solvers.cpp
@@ -14,7 +14,7 @@
 #include <benchmark/benchmark.h>
 
 #include <Eigen/Cholesky>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include <Eigen/LU>
 
 using namespace Eigen;
diff --git a/unsupported/benchmarks/GPU/bench_unified_memory.cpp b/contrib/benchmarks/GPU/bench_unified_memory.cpp
similarity index 99%
rename from unsupported/benchmarks/GPU/bench_unified_memory.cpp
rename to contrib/benchmarks/GPU/bench_unified_memory.cpp
index a4c091f..dc643a5 100644
--- a/unsupported/benchmarks/GPU/bench_unified_memory.cpp
+++ b/contrib/benchmarks/GPU/bench_unified_memory.cpp
@@ -35,7 +35,7 @@
 //   Registered     cudaHostRegister over the host matrix's own storage
 //
 // Build (standalone project, see CMakeLists.txt in this directory):
-//   cmake -G Ninja -B build-bench-gpu -S unsupported/benchmarks/GPU \
+//   cmake -G Ninja -B build-bench-gpu -S contrib/benchmarks/GPU \
 //         -DCMAKE_CUDA_ARCHITECTURES=87
 //   cmake --build build-bench-gpu --target bench_unified_memory
 //   ./build-bench-gpu/bench_unified_memory
@@ -44,7 +44,7 @@
 #define EIGEN_USE_GPU
 #endif
 #include <Eigen/Core>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include <benchmark/benchmark.h>
 #include <cublas_v2.h>
diff --git a/unsupported/benchmarks/KroneckerProduct/CMakeLists.txt b/contrib/benchmarks/KroneckerProduct/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/KroneckerProduct/CMakeLists.txt
rename to contrib/benchmarks/KroneckerProduct/CMakeLists.txt
diff --git a/unsupported/benchmarks/KroneckerProduct/bench_kronecker.cpp b/contrib/benchmarks/KroneckerProduct/bench_kronecker.cpp
similarity index 97%
rename from unsupported/benchmarks/KroneckerProduct/bench_kronecker.cpp
rename to contrib/benchmarks/KroneckerProduct/bench_kronecker.cpp
index fdc2db8..ce5f90b 100644
--- a/unsupported/benchmarks/KroneckerProduct/bench_kronecker.cpp
+++ b/contrib/benchmarks/KroneckerProduct/bench_kronecker.cpp
@@ -5,7 +5,7 @@
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/KroneckerProduct>
+#include <contrib/Eigen/KroneckerProduct>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/MatrixFunctions/CMakeLists.txt b/contrib/benchmarks/MatrixFunctions/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/MatrixFunctions/CMakeLists.txt
rename to contrib/benchmarks/MatrixFunctions/CMakeLists.txt
diff --git a/unsupported/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp b/contrib/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp
similarity index 96%
rename from unsupported/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp
rename to contrib/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp
index 3a9a704..974ab43 100644
--- a/unsupported/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp
+++ b/contrib/benchmarks/MatrixFunctions/bench_matrix_exponential.cpp
@@ -5,7 +5,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp b/contrib/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp
similarity index 96%
rename from unsupported/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp
rename to contrib/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp
index 456f668..352415a 100644
--- a/unsupported/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp
+++ b/contrib/benchmarks/MatrixFunctions/bench_matrix_logarithm.cpp
@@ -5,7 +5,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/MatrixFunctions/bench_matrix_power.cpp b/contrib/benchmarks/MatrixFunctions/bench_matrix_power.cpp
similarity index 97%
rename from unsupported/benchmarks/MatrixFunctions/bench_matrix_power.cpp
rename to contrib/benchmarks/MatrixFunctions/bench_matrix_power.cpp
index 448271c..1f1c98a 100644
--- a/unsupported/benchmarks/MatrixFunctions/bench_matrix_power.cpp
+++ b/contrib/benchmarks/MatrixFunctions/bench_matrix_power.cpp
@@ -4,7 +4,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/SpecialFunctions/CMakeLists.txt b/contrib/benchmarks/SpecialFunctions/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/SpecialFunctions/CMakeLists.txt
rename to contrib/benchmarks/SpecialFunctions/CMakeLists.txt
diff --git a/unsupported/benchmarks/SpecialFunctions/bench_special_functions.cpp b/contrib/benchmarks/SpecialFunctions/bench_special_functions.cpp
similarity index 99%
rename from unsupported/benchmarks/SpecialFunctions/bench_special_functions.cpp
rename to contrib/benchmarks/SpecialFunctions/bench_special_functions.cpp
index 9a132e0..6460f84 100644
--- a/unsupported/benchmarks/SpecialFunctions/bench_special_functions.cpp
+++ b/contrib/benchmarks/SpecialFunctions/bench_special_functions.cpp
@@ -6,7 +6,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/SpecialFunctions>
+#include <contrib/Eigen/SpecialFunctions>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Splines/CMakeLists.txt b/contrib/benchmarks/Splines/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/Splines/CMakeLists.txt
rename to contrib/benchmarks/Splines/CMakeLists.txt
diff --git a/unsupported/benchmarks/Splines/bench_splines.cpp b/contrib/benchmarks/Splines/bench_splines.cpp
similarity index 98%
rename from unsupported/benchmarks/Splines/bench_splines.cpp
rename to contrib/benchmarks/Splines/bench_splines.cpp
index af90276..ac4a7af 100644
--- a/unsupported/benchmarks/Splines/bench_splines.cpp
+++ b/contrib/benchmarks/Splines/bench_splines.cpp
@@ -5,7 +5,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/Splines>
+#include <contrib/Eigen/Splines>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/CMakeLists.txt b/contrib/benchmarks/StructuredMatrices/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/StructuredMatrices/CMakeLists.txt
rename to contrib/benchmarks/StructuredMatrices/CMakeLists.txt
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_circulant.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_circulant.cpp
similarity index 99%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_circulant.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_circulant.cpp
index 637e8ce..8e9801e 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_circulant.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_circulant.cpp
@@ -9,7 +9,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Dense>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_dplr.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_dplr.cpp
similarity index 97%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_dplr.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_dplr.cpp
index e22aa06..706da5b 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_dplr.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_dplr.cpp
@@ -9,7 +9,7 @@
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
 #include <Eigen/LU>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_hankel.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_hankel.cpp
similarity index 98%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_hankel.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_hankel.cpp
index f39fda9..dd0b8f2 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_hankel.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_hankel.cpp
@@ -7,7 +7,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_kronecker.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_kronecker.cpp
similarity index 99%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_kronecker.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_kronecker.cpp
index 3a5076e..7d8e45e 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_kronecker.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_kronecker.cpp
@@ -10,7 +10,7 @@
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
 #include <Eigen/LU>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_levinson.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_levinson.cpp
similarity index 98%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_levinson.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_levinson.cpp
index 808be8d..6a15e07 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_levinson.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_levinson.cpp
@@ -7,7 +7,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Dense>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_toeplitz.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_toeplitz.cpp
similarity index 98%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_toeplitz.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_toeplitz.cpp
index 66b906a..bc39bef 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_toeplitz.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_toeplitz.cpp
@@ -6,7 +6,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Dense>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_transpose.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_transpose.cpp
similarity index 98%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_transpose.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_transpose.cpp
index c7f00ba..069659b 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_transpose.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_transpose.cpp
@@ -8,7 +8,7 @@
 
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/StructuredMatrices/bench_structured_vandermonde.cpp b/contrib/benchmarks/StructuredMatrices/bench_structured_vandermonde.cpp
similarity index 98%
rename from unsupported/benchmarks/StructuredMatrices/bench_structured_vandermonde.cpp
rename to contrib/benchmarks/StructuredMatrices/bench_structured_vandermonde.cpp
index 05c7b9d..2704ae6 100644
--- a/unsupported/benchmarks/StructuredMatrices/bench_structured_vandermonde.cpp
+++ b/contrib/benchmarks/StructuredMatrices/bench_structured_vandermonde.cpp
@@ -12,7 +12,7 @@
 #include <benchmark/benchmark.h>
 #include <Eigen/Core>
 #include <Eigen/LU>
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/CMakeLists.txt b/contrib/benchmarks/Tensor/CMakeLists.txt
similarity index 100%
rename from unsupported/benchmarks/Tensor/CMakeLists.txt
rename to contrib/benchmarks/Tensor/CMakeLists.txt
diff --git a/unsupported/benchmarks/Tensor/bench_broadcasting.cpp b/contrib/benchmarks/Tensor/bench_broadcasting.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_broadcasting.cpp
rename to contrib/benchmarks/Tensor/bench_broadcasting.cpp
index fe10fd3..f79258a 100644
--- a/unsupported/benchmarks/Tensor/bench_broadcasting.cpp
+++ b/contrib/benchmarks/Tensor/bench_broadcasting.cpp
@@ -6,8 +6,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_chained_expressions.cpp b/contrib/benchmarks/Tensor/bench_chained_expressions.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_chained_expressions.cpp
rename to contrib/benchmarks/Tensor/bench_chained_expressions.cpp
index 6084f24..fb43683 100644
--- a/unsupported/benchmarks/Tensor/bench_chained_expressions.cpp
+++ b/contrib/benchmarks/Tensor/bench_chained_expressions.cpp
@@ -6,8 +6,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_coefficient_wise.cpp b/contrib/benchmarks/Tensor/bench_coefficient_wise.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_coefficient_wise.cpp
rename to contrib/benchmarks/Tensor/bench_coefficient_wise.cpp
index e9a3b2c..13500c2 100644
--- a/unsupported/benchmarks/Tensor/bench_coefficient_wise.cpp
+++ b/contrib/benchmarks/Tensor/bench_coefficient_wise.cpp
@@ -6,9 +6,9 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/SpecialFunctions>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/SpecialFunctions>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_concatenation.cpp b/contrib/benchmarks/Tensor/bench_concatenation.cpp
similarity index 99%
rename from unsupported/benchmarks/Tensor/bench_concatenation.cpp
rename to contrib/benchmarks/Tensor/bench_concatenation.cpp
index 9e53b9a..5c9d675 100644
--- a/unsupported/benchmarks/Tensor/bench_concatenation.cpp
+++ b/contrib/benchmarks/Tensor/bench_concatenation.cpp
@@ -10,8 +10,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_contraction.cpp b/contrib/benchmarks/Tensor/bench_contraction.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_contraction.cpp
rename to contrib/benchmarks/Tensor/bench_contraction.cpp
index 20b6c60..cd36154 100644
--- a/unsupported/benchmarks/Tensor/bench_contraction.cpp
+++ b/contrib/benchmarks/Tensor/bench_contraction.cpp
@@ -6,8 +6,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_convolution.cpp b/contrib/benchmarks/Tensor/bench_convolution.cpp
similarity index 97%
rename from unsupported/benchmarks/Tensor/bench_convolution.cpp
rename to contrib/benchmarks/Tensor/bench_convolution.cpp
index 4637c99..0c87588 100644
--- a/unsupported/benchmarks/Tensor/bench_convolution.cpp
+++ b/contrib/benchmarks/Tensor/bench_convolution.cpp
@@ -5,8 +5,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_custom_op.cpp b/contrib/benchmarks/Tensor/bench_custom_op.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_custom_op.cpp
rename to contrib/benchmarks/Tensor/bench_custom_op.cpp
index ea46ec7..97d3096 100644
--- a/unsupported/benchmarks/Tensor/bench_custom_op.cpp
+++ b/contrib/benchmarks/Tensor/bench_custom_op.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_image_patch.cpp b/contrib/benchmarks/Tensor/bench_image_patch.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_image_patch.cpp
rename to contrib/benchmarks/Tensor/bench_image_patch.cpp
index 027777b..1754900 100644
--- a/unsupported/benchmarks/Tensor/bench_image_patch.cpp
+++ b/contrib/benchmarks/Tensor/bench_image_patch.cpp
@@ -5,8 +5,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_inflation.cpp b/contrib/benchmarks/Tensor/bench_inflation.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_inflation.cpp
rename to contrib/benchmarks/Tensor/bench_inflation.cpp
index 7530bc1..21a12be 100644
--- a/unsupported/benchmarks/Tensor/bench_inflation.cpp
+++ b/contrib/benchmarks/Tensor/bench_inflation.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_layout_swap.cpp b/contrib/benchmarks/Tensor/bench_layout_swap.cpp
similarity index 99%
rename from unsupported/benchmarks/Tensor/bench_layout_swap.cpp
rename to contrib/benchmarks/Tensor/bench_layout_swap.cpp
index e85dd7d..e330d36 100644
--- a/unsupported/benchmarks/Tensor/bench_layout_swap.cpp
+++ b/contrib/benchmarks/Tensor/bench_layout_swap.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_morphing.cpp b/contrib/benchmarks/Tensor/bench_morphing.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_morphing.cpp
rename to contrib/benchmarks/Tensor/bench_morphing.cpp
index 784e6ee..d0a4b52 100644
--- a/unsupported/benchmarks/Tensor/bench_morphing.cpp
+++ b/contrib/benchmarks/Tensor/bench_morphing.cpp
@@ -5,8 +5,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_patch.cpp b/contrib/benchmarks/Tensor/bench_patch.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_patch.cpp
rename to contrib/benchmarks/Tensor/bench_patch.cpp
index 741141f..31d83ab 100644
--- a/unsupported/benchmarks/Tensor/bench_patch.cpp
+++ b/contrib/benchmarks/Tensor/bench_patch.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_reduction.cpp b/contrib/benchmarks/Tensor/bench_reduction.cpp
similarity index 97%
rename from unsupported/benchmarks/Tensor/bench_reduction.cpp
rename to contrib/benchmarks/Tensor/bench_reduction.cpp
index 68e9575..06994a9 100644
--- a/unsupported/benchmarks/Tensor/bench_reduction.cpp
+++ b/contrib/benchmarks/Tensor/bench_reduction.cpp
@@ -6,8 +6,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_reverse.cpp b/contrib/benchmarks/Tensor/bench_reverse.cpp
similarity index 99%
rename from unsupported/benchmarks/Tensor/bench_reverse.cpp
rename to contrib/benchmarks/Tensor/bench_reverse.cpp
index 330b040..f5b32b6 100644
--- a/unsupported/benchmarks/Tensor/bench_reverse.cpp
+++ b/contrib/benchmarks/Tensor/bench_reverse.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_roll.cpp b/contrib/benchmarks/Tensor/bench_roll.cpp
similarity index 99%
rename from unsupported/benchmarks/Tensor/bench_roll.cpp
rename to contrib/benchmarks/Tensor/bench_roll.cpp
index 5fea5f9..603cc13 100644
--- a/unsupported/benchmarks/Tensor/bench_roll.cpp
+++ b/contrib/benchmarks/Tensor/bench_roll.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_shuffling.cpp b/contrib/benchmarks/Tensor/bench_shuffling.cpp
similarity index 98%
rename from unsupported/benchmarks/Tensor/bench_shuffling.cpp
rename to contrib/benchmarks/Tensor/bench_shuffling.cpp
index ef21dae..21e9b89 100644
--- a/unsupported/benchmarks/Tensor/bench_shuffling.cpp
+++ b/contrib/benchmarks/Tensor/bench_shuffling.cpp
@@ -5,8 +5,8 @@
 #define EIGEN_USE_THREADS
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
-#include <unsupported/Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
+#include <Eigen/ThreadPool>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_striding.cpp b/contrib/benchmarks/Tensor/bench_striding.cpp
similarity index 99%
rename from unsupported/benchmarks/Tensor/bench_striding.cpp
rename to contrib/benchmarks/Tensor/bench_striding.cpp
index f924cab..6b9efc0 100644
--- a/unsupported/benchmarks/Tensor/bench_striding.cpp
+++ b/contrib/benchmarks/Tensor/bench_striding.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_tensor_fft.cpp b/contrib/benchmarks/Tensor/bench_tensor_fft.cpp
similarity index 99%
rename from unsupported/benchmarks/Tensor/bench_tensor_fft.cpp
rename to contrib/benchmarks/Tensor/bench_tensor_fft.cpp
index 28b1f52..193b1ab 100644
--- a/unsupported/benchmarks/Tensor/bench_tensor_fft.cpp
+++ b/contrib/benchmarks/Tensor/bench_tensor_fft.cpp
@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using namespace Eigen;
 
diff --git a/unsupported/benchmarks/Tensor/bench_threadpool_device.cpp b/contrib/benchmarks/Tensor/bench_threadpool_device.cpp
similarity index 97%
rename from unsupported/benchmarks/Tensor/bench_threadpool_device.cpp
rename to contrib/benchmarks/Tensor/bench_threadpool_device.cpp
index a426ee9..3aba55a 100644
--- a/unsupported/benchmarks/Tensor/bench_threadpool_device.cpp
+++ b/contrib/benchmarks/Tensor/bench_threadpool_device.cpp
@@ -10,8 +10,8 @@
 #include <mutex>
 
 #include <benchmark/benchmark.h>
-#include <unsupported/Eigen/CXX11/ThreadPool>
-#include <unsupported/Eigen/CXX11/Tensor>
+#include <Eigen/ThreadPool>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Index;
 using Eigen::TensorOpCost;
diff --git a/unsupported/doc/AutoDiff.dox b/contrib/doc/AutoDiff.dox
similarity index 100%
rename from unsupported/doc/AutoDiff.dox
rename to contrib/doc/AutoDiff.dox
diff --git a/unsupported/doc/CMakeLists.txt b/contrib/doc/CMakeLists.txt
similarity index 100%
rename from unsupported/doc/CMakeLists.txt
rename to contrib/doc/CMakeLists.txt
diff --git a/unsupported/doc/Overview.dox b/contrib/doc/Overview.dox
similarity index 76%
rename from unsupported/doc/Overview.dox
rename to contrib/doc/Overview.dox
index bc44565..14228d1 100644
--- a/unsupported/doc/Overview.dox
+++ b/contrib/doc/Overview.dox
@@ -3,11 +3,11 @@
 
 /** \mainpage notitle
 
-This is the API documentation for %Eigen's unsupported modules.
+This is the API documentation for %Eigen's contrib modules.
 
 These modules are contributions from various users. They are provided "as is", without any support.
 
-Click on the \e Modules tab at the top of this page to get a list of all unsupported modules.
+Click on the \e Modules tab at the top of this page to get a list of all contrib modules.
 
 Don't miss the <a href="../index.html">official Eigen documentation</a>.
 
@@ -19,9 +19,9 @@
 
 /*
 
-\defgroup Unsupported_modules Unsupported modules
+\defgroup Contributed_modules Contributed modules
 
-The unsupported modules are contributions from various users. They are
+The contrib modules are contributions from various users. They are
 provided "as is", without any support. Nevertheless, some of them are
 subject to be included in %Eigen in the future.
 
diff --git a/unsupported/doc/SYCL.dox b/contrib/doc/SYCL.dox
similarity index 100%
rename from unsupported/doc/SYCL.dox
rename to contrib/doc/SYCL.dox
diff --git a/unsupported/doc/eigendoxy_layout.xml.in b/contrib/doc/eigendoxy_layout.xml.in
similarity index 100%
rename from unsupported/doc/eigendoxy_layout.xml.in
rename to contrib/doc/eigendoxy_layout.xml.in
diff --git a/unsupported/doc/examples/AutoDiffJacobianExample.cpp b/contrib/doc/examples/AutoDiffJacobianExample.cpp
similarity index 95%
rename from unsupported/doc/examples/AutoDiffJacobianExample.cpp
rename to contrib/doc/examples/AutoDiffJacobianExample.cpp
index 2324d84..45b4bcb 100644
--- a/unsupported/doc/examples/AutoDiffJacobianExample.cpp
+++ b/contrib/doc/examples/AutoDiffJacobianExample.cpp
@@ -4,7 +4,7 @@
 #include <Eigen/Dense>
 #include <cmath>
 #include <iostream>
-#include <unsupported/Eigen/AutoDiff>
+#include <contrib/Eigen/AutoDiff>
 
 struct ExampleFunctor {
   typedef Eigen::Vector2d InputType;
diff --git a/unsupported/doc/examples/AutoDiffScalarExample.cpp b/contrib/doc/examples/AutoDiffScalarExample.cpp
similarity index 93%
rename from unsupported/doc/examples/AutoDiffScalarExample.cpp
rename to contrib/doc/examples/AutoDiffScalarExample.cpp
index 905d5a4..99f0690 100644
--- a/unsupported/doc/examples/AutoDiffScalarExample.cpp
+++ b/contrib/doc/examples/AutoDiffScalarExample.cpp
@@ -4,7 +4,7 @@
 #include <Eigen/Dense>
 #include <cmath>
 #include <iostream>
-#include <unsupported/Eigen/AutoDiff>
+#include <contrib/Eigen/AutoDiff>
 
 template <typename Scalar>
 Scalar f(const Scalar& x, const Scalar& y) {
diff --git a/unsupported/doc/examples/BVH_Example.cpp b/contrib/doc/examples/BVH_Example.cpp
similarity index 98%
rename from unsupported/doc/examples/BVH_Example.cpp
rename to contrib/doc/examples/BVH_Example.cpp
index 1f5e401..9768c59 100644
--- a/unsupported/doc/examples/BVH_Example.cpp
+++ b/contrib/doc/examples/BVH_Example.cpp
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <Eigen/StdVector>
-#include <unsupported/Eigen/BVH>
+#include <contrib/Eigen/BVH>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/CMakeLists.txt b/contrib/doc/examples/CMakeLists.txt
similarity index 87%
rename from unsupported/doc/examples/CMakeLists.txt
rename to contrib/doc/examples/CMakeLists.txt
index 301e799..a684712 100644
--- a/unsupported/doc/examples/CMakeLists.txt
+++ b/contrib/doc/examples/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 file(GLOB examples_SRCS "*.cpp")
 
-add_custom_target(unsupported_examples)
+add_custom_target(contrib_examples)
 
 foreach(example_src ${examples_SRCS})
   get_filename_component(example ${example_src} NAME_WE)
@@ -18,7 +18,7 @@
     COMMAND example_${example}
     ARGS >${CMAKE_CURRENT_BINARY_DIR}/${example}.out
   )
-  add_dependencies(unsupported_examples example_${example})
+  add_dependencies(contrib_examples example_${example})
 endforeach(example_src)
 
 if(EIGEN_TEST_SYCL)
diff --git a/unsupported/doc/examples/EulerAngles.cpp b/contrib/doc/examples/EulerAngles.cpp
similarity index 97%
rename from unsupported/doc/examples/EulerAngles.cpp
rename to contrib/doc/examples/EulerAngles.cpp
index e417b31..5fb6dee 100644
--- a/unsupported/doc/examples/EulerAngles.cpp
+++ b/contrib/doc/examples/EulerAngles.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/EulerAngles>
+#include <contrib/Eigen/EulerAngles>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/FFT.cpp b/contrib/doc/examples/FFT.cpp
similarity index 98%
rename from unsupported/doc/examples/FFT.cpp
rename to contrib/doc/examples/FFT.cpp
index 56bb830..220ad34 100644
--- a/unsupported/doc/examples/FFT.cpp
+++ b/contrib/doc/examples/FFT.cpp
@@ -16,7 +16,7 @@
 #include <iterator>
 #include <iostream>
 #include <Eigen/Core>
-#include <unsupported/Eigen/FFT>
+#include <contrib/Eigen/FFT>
 
 using namespace std;
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixExponential.cpp b/contrib/doc/examples/MatrixExponential.cpp
similarity index 88%
rename from unsupported/doc/examples/MatrixExponential.cpp
rename to contrib/doc/examples/MatrixExponential.cpp
index bec49b9..25143d2 100644
--- a/unsupported/doc/examples/MatrixExponential.cpp
+++ b/contrib/doc/examples/MatrixExponential.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixFunction.cpp b/contrib/doc/examples/MatrixFunction.cpp
similarity index 90%
rename from unsupported/doc/examples/MatrixFunction.cpp
rename to contrib/doc/examples/MatrixFunction.cpp
index a20ccb3..aeac506 100644
--- a/unsupported/doc/examples/MatrixFunction.cpp
+++ b/contrib/doc/examples/MatrixFunction.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixLogarithm.cpp b/contrib/doc/examples/MatrixLogarithm.cpp
similarity index 89%
rename from unsupported/doc/examples/MatrixLogarithm.cpp
rename to contrib/doc/examples/MatrixLogarithm.cpp
index 6926028..dee2471 100644
--- a/unsupported/doc/examples/MatrixLogarithm.cpp
+++ b/contrib/doc/examples/MatrixLogarithm.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixPower.cpp b/contrib/doc/examples/MatrixPower.cpp
similarity index 90%
rename from unsupported/doc/examples/MatrixPower.cpp
rename to contrib/doc/examples/MatrixPower.cpp
index bef161e..da776a1 100644
--- a/unsupported/doc/examples/MatrixPower.cpp
+++ b/contrib/doc/examples/MatrixPower.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixPower_optimal.cpp b/contrib/doc/examples/MatrixPower_optimal.cpp
similarity index 92%
rename from unsupported/doc/examples/MatrixPower_optimal.cpp
rename to contrib/doc/examples/MatrixPower_optimal.cpp
index 2e0cbd3..fba0b86 100644
--- a/unsupported/doc/examples/MatrixPower_optimal.cpp
+++ b/contrib/doc/examples/MatrixPower_optimal.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixSine.cpp b/contrib/doc/examples/MatrixSine.cpp
similarity index 92%
rename from unsupported/doc/examples/MatrixSine.cpp
rename to contrib/doc/examples/MatrixSine.cpp
index a144641..5abeaad 100644
--- a/unsupported/doc/examples/MatrixSine.cpp
+++ b/contrib/doc/examples/MatrixSine.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixSinh.cpp b/contrib/doc/examples/MatrixSinh.cpp
similarity index 92%
rename from unsupported/doc/examples/MatrixSinh.cpp
rename to contrib/doc/examples/MatrixSinh.cpp
index 0b1418f..d9b0816 100644
--- a/unsupported/doc/examples/MatrixSinh.cpp
+++ b/contrib/doc/examples/MatrixSinh.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/MatrixSquareRoot.cpp b/contrib/doc/examples/MatrixSquareRoot.cpp
similarity index 90%
rename from unsupported/doc/examples/MatrixSquareRoot.cpp
rename to contrib/doc/examples/MatrixSquareRoot.cpp
index 5837d2b..2f054ff 100644
--- a/unsupported/doc/examples/MatrixSquareRoot.cpp
+++ b/contrib/doc/examples/MatrixSquareRoot.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/PolynomialSolver1.cpp b/contrib/doc/examples/PolynomialSolver1.cpp
similarity index 97%
rename from unsupported/doc/examples/PolynomialSolver1.cpp
rename to contrib/doc/examples/PolynomialSolver1.cpp
index 7bec9a7..0a15df1 100644
--- a/unsupported/doc/examples/PolynomialSolver1.cpp
+++ b/contrib/doc/examples/PolynomialSolver1.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/Polynomials>
+#include <contrib/Eigen/Polynomials>
 #include <vector>
 #include <iostream>
 
diff --git a/unsupported/doc/examples/PolynomialUtils1.cpp b/contrib/doc/examples/PolynomialUtils1.cpp
similarity index 94%
rename from unsupported/doc/examples/PolynomialUtils1.cpp
rename to contrib/doc/examples/PolynomialUtils1.cpp
index c7638bc..c8d1fd2 100644
--- a/unsupported/doc/examples/PolynomialUtils1.cpp
+++ b/contrib/doc/examples/PolynomialUtils1.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include <unsupported/Eigen/Polynomials>
+#include <contrib/Eigen/Polynomials>
 #include <iostream>
 
 using namespace Eigen;
diff --git a/unsupported/doc/examples/SYCL/CMakeLists.txt b/contrib/doc/examples/SYCL/CMakeLists.txt
similarity index 94%
rename from unsupported/doc/examples/SYCL/CMakeLists.txt
rename to contrib/doc/examples/SYCL/CMakeLists.txt
index eb7b82b..2522488 100644
--- a/unsupported/doc/examples/SYCL/CMakeLists.txt
+++ b/contrib/doc/examples/SYCL/CMakeLists.txt
@@ -29,6 +29,6 @@
 FOREACH(example_src ${examples_SRCS})
   GET_FILENAME_COMPONENT(example ${example_src} NAME_WE)
   ei_add_test_internal(${example} example_${example})
-  ADD_DEPENDENCIES(unsupported_examples example_${example})
+  ADD_DEPENDENCIES(contrib_examples example_${example})
 ENDFOREACH(example_src)
 set(EIGEN_SYCL OFF)
diff --git a/unsupported/doc/examples/SYCL/CwiseMul.cpp b/contrib/doc/examples/SYCL/CwiseMul.cpp
similarity index 98%
rename from unsupported/doc/examples/SYCL/CwiseMul.cpp
rename to contrib/doc/examples/SYCL/CwiseMul.cpp
index ccd6674..63d698a 100644
--- a/unsupported/doc/examples/SYCL/CwiseMul.cpp
+++ b/contrib/doc/examples/SYCL/CwiseMul.cpp
@@ -3,7 +3,7 @@
 
 #include <iostream>
 #define EIGEN_USE_SYCL
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/doc/snippets/CMakeLists.txt b/contrib/doc/snippets/CMakeLists.txt
similarity index 90%
rename from unsupported/doc/snippets/CMakeLists.txt
rename to contrib/doc/snippets/CMakeLists.txt
index b7a4e07..6b2268a 100644
--- a/unsupported/doc/snippets/CMakeLists.txt
+++ b/contrib/doc/snippets/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 file(GLOB snippets_SRCS "*.cpp")
 
-add_custom_target(unsupported_snippets)
+add_custom_target(contrib_snippets)
 
 foreach(snippet_src ${snippets_SRCS})
   get_filename_component(snippet ${snippet_src} NAME_WE)
@@ -23,7 +23,7 @@
     COMMAND ${compile_snippet_target}
     ARGS >${CMAKE_CURRENT_BINARY_DIR}/${snippet}.out
   )
-  add_dependencies(unsupported_snippets ${compile_snippet_target})
+  add_dependencies(contrib_snippets ${compile_snippet_target})
   set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${compile_snippet_src}
                               PROPERTIES OBJECT_DEPENDS ${snippet_src})
 endforeach(snippet_src)
diff --git a/unsupported/test/BVH.cpp b/contrib/test/BVH.cpp
similarity index 99%
rename from unsupported/test/BVH.cpp
rename to contrib/test/BVH.cpp
index 0286c01..5a5399b 100644
--- a/unsupported/test/BVH.cpp
+++ b/contrib/test/BVH.cpp
@@ -11,7 +11,7 @@
 #include "main.h"
 #include <Eigen/StdVector>
 #include <Eigen/Geometry>
-#include <unsupported/Eigen/BVH>
+#include <contrib/Eigen/BVH>
 
 namespace Eigen {
 
diff --git a/unsupported/test/CMakeLists.txt b/contrib/test/CMakeLists.txt
similarity index 98%
rename from unsupported/test/CMakeLists.txt
rename to contrib/test/CMakeLists.txt
index 17078a0..ded2f7b 100644
--- a/unsupported/test/CMakeLists.txt
+++ b/contrib/test/CMakeLists.txt
@@ -6,10 +6,10 @@
   file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h)
 endif()
 
-set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Unsupported")
-add_custom_target(BuildUnsupported)
+set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Contrib")
+add_custom_target(BuildContrib)
 
-include_directories(../../test ../../unsupported
+include_directories(../../test ../../contrib
                     ${CMAKE_CURRENT_BINARY_DIR}/../../test)
 
 find_package (Threads)
diff --git a/unsupported/test/EulerAngles.cpp b/contrib/test/EulerAngles.cpp
similarity index 99%
rename from unsupported/test/EulerAngles.cpp
rename to contrib/test/EulerAngles.cpp
index cd275e6..150e7d2 100644
--- a/unsupported/test/EulerAngles.cpp
+++ b/contrib/test/EulerAngles.cpp
@@ -12,7 +12,7 @@
 
 EIGEN_DISABLE_DEPRECATED_WARNING
 
-#include <unsupported/Eigen/EulerAngles>
+#include <contrib/Eigen/EulerAngles>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/FFT.cpp b/contrib/test/FFT.cpp
similarity index 100%
rename from unsupported/test/FFT.cpp
rename to contrib/test/FFT.cpp
diff --git a/unsupported/test/FFTW.cpp b/contrib/test/FFTW.cpp
similarity index 100%
rename from unsupported/test/FFTW.cpp
rename to contrib/test/FFTW.cpp
diff --git a/unsupported/test/GPU/CMakeLists.txt b/contrib/test/GPU/CMakeLists.txt
similarity index 97%
rename from unsupported/test/GPU/CMakeLists.txt
rename to contrib/test/GPU/CMakeLists.txt
index 381e93c..3a846fa 100644
--- a/unsupported/test/GPU/CMakeLists.txt
+++ b/contrib/test/GPU/CMakeLists.txt
@@ -1,4 +1,4 @@
-# GPU module tests. Included from unsupported/test/CMakeLists.txt inside the
+# GPU module tests. Included from contrib/test/CMakeLists.txt inside the
 # if(CUDA_FOUND AND EIGEN_TEST_CUDA) block.
 # SPDX-FileCopyrightText: The Eigen Authors
 # SPDX-License-Identifier: MPL-2.0
@@ -74,7 +74,7 @@
 endfunction()
 
 # Compile-time GPU type-trait surface (static_assert only; links like device_matrix
-# because it pulls the full <unsupported/Eigen/GPU> umbrella).
+# because it pulls the full <contrib/Eigen/GPU> umbrella).
 ei_add_gpu_test(device_traits
   EXTRA_LIBS CUDA::cublas CUDA::cusolver CUDA::npps CUDA::nppc)
 
diff --git a/unsupported/test/GPU/cg.cpp b/contrib/test/GPU/cg.cpp
similarity index 99%
rename from unsupported/test/GPU/cg.cpp
rename to contrib/test/GPU/cg.cpp
index c1789f7..4383ec2 100644
--- a/unsupported/test/GPU/cg.cpp
+++ b/contrib/test/GPU/cg.cpp
@@ -17,7 +17,7 @@
 #include "main.h"
 #include <Eigen/Sparse>
 #include <Eigen/IterativeLinearSolvers>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include "gpu_test_helpers.h"
 
 using namespace Eigen;
diff --git a/unsupported/test/GPU/cublas.cpp b/contrib/test/GPU/cublas.cpp
similarity index 99%
rename from unsupported/test/GPU/cublas.cpp
rename to contrib/test/GPU/cublas.cpp
index 2ee5e2b..2e581d7 100644
--- a/unsupported/test/GPU/cublas.cpp
+++ b/contrib/test/GPU/cublas.cpp
@@ -13,7 +13,7 @@
 
 #define EIGEN_USE_GPU
 #include "main.h"
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include "./gpu_test_helpers.h"
 
diff --git a/unsupported/test/GPU/cublas_64bit.cpp b/contrib/test/GPU/cublas_64bit.cpp
similarity index 97%
rename from unsupported/test/GPU/cublas_64bit.cpp
rename to contrib/test/GPU/cublas_64bit.cpp
index cd1cfa7..3610228 100644
--- a/unsupported/test/GPU/cublas_64bit.cpp
+++ b/contrib/test/GPU/cublas_64bit.cpp
@@ -5,7 +5,7 @@
 
 #define EIGEN_USE_GPU
 #include "main.h"
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/GPU/cudss_ldlt.cpp b/contrib/test/GPU/cudss_ldlt.cpp
similarity index 99%
rename from unsupported/test/GPU/cudss_ldlt.cpp
rename to contrib/test/GPU/cudss_ldlt.cpp
index 50cbb95..51ba049 100644
--- a/unsupported/test/GPU/cudss_ldlt.cpp
+++ b/contrib/test/GPU/cudss_ldlt.cpp
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include "gpu_test_helpers.h"
 
 using namespace Eigen;
diff --git a/unsupported/test/GPU/cudss_llt.cpp b/contrib/test/GPU/cudss_llt.cpp
similarity index 99%
rename from unsupported/test/GPU/cudss_llt.cpp
rename to contrib/test/GPU/cudss_llt.cpp
index d28c506..3e1eeab 100644
--- a/unsupported/test/GPU/cudss_llt.cpp
+++ b/contrib/test/GPU/cudss_llt.cpp
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include "gpu_test_helpers.h"
 
 using namespace Eigen;
diff --git a/unsupported/test/GPU/cudss_lu.cpp b/contrib/test/GPU/cudss_lu.cpp
similarity index 99%
rename from unsupported/test/GPU/cudss_lu.cpp
rename to contrib/test/GPU/cudss_lu.cpp
index 89d17bd..b108674 100644
--- a/unsupported/test/GPU/cudss_lu.cpp
+++ b/contrib/test/GPU/cudss_lu.cpp
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include "gpu_test_helpers.h"
 
 using namespace Eigen;
diff --git a/unsupported/test/GPU/cufft.cpp b/contrib/test/GPU/cufft.cpp
similarity index 99%
rename from unsupported/test/GPU/cufft.cpp
rename to contrib/test/GPU/cufft.cpp
index f26524e..abdc9d3 100644
--- a/unsupported/test/GPU/cufft.cpp
+++ b/contrib/test/GPU/cufft.cpp
@@ -12,7 +12,7 @@
 
 #define EIGEN_USE_GPU
 #include "main.h"
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include "gpu_test_helpers.h"
 
 using namespace Eigen;
diff --git a/unsupported/test/GPU/cusolver_eigen.cpp b/contrib/test/GPU/cusolver_eigen.cpp
similarity index 99%
rename from unsupported/test/GPU/cusolver_eigen.cpp
rename to contrib/test/GPU/cusolver_eigen.cpp
index f792474..c93f3e9 100644
--- a/unsupported/test/GPU/cusolver_eigen.cpp
+++ b/contrib/test/GPU/cusolver_eigen.cpp
@@ -14,7 +14,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Eigenvalues>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include "./gpu_test_helpers.h"
 
diff --git a/unsupported/test/GPU/cusolver_llt.cpp b/contrib/test/GPU/cusolver_llt.cpp
similarity index 99%
rename from unsupported/test/GPU/cusolver_llt.cpp
rename to contrib/test/GPU/cusolver_llt.cpp
index 4078389..f70b6db 100644
--- a/unsupported/test/GPU/cusolver_llt.cpp
+++ b/contrib/test/GPU/cusolver_llt.cpp
@@ -15,7 +15,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Cholesky>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include <atomic>
 #include <chrono>
 #include <thread>
diff --git a/unsupported/test/GPU/cusolver_lu.cpp b/contrib/test/GPU/cusolver_lu.cpp
similarity index 99%
rename from unsupported/test/GPU/cusolver_lu.cpp
rename to contrib/test/GPU/cusolver_lu.cpp
index 534ee51..44325db 100644
--- a/unsupported/test/GPU/cusolver_lu.cpp
+++ b/contrib/test/GPU/cusolver_lu.cpp
@@ -14,7 +14,7 @@
 //
 #define EIGEN_USE_GPU
 #include "main.h"
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include "./gpu_test_helpers.h"
 
diff --git a/unsupported/test/GPU/cusolver_qr.cpp b/contrib/test/GPU/cusolver_qr.cpp
similarity index 99%
rename from unsupported/test/GPU/cusolver_qr.cpp
rename to contrib/test/GPU/cusolver_qr.cpp
index 84d22db..066ea69 100644
--- a/unsupported/test/GPU/cusolver_qr.cpp
+++ b/contrib/test/GPU/cusolver_qr.cpp
@@ -14,7 +14,7 @@
 #include "main.h"
 #include <Eigen/QR>
 #include <Eigen/SVD>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include "./gpu_test_helpers.h"
 
diff --git a/unsupported/test/GPU/cusolver_svd.cpp b/contrib/test/GPU/cusolver_svd.cpp
similarity index 99%
rename from unsupported/test/GPU/cusolver_svd.cpp
rename to contrib/test/GPU/cusolver_svd.cpp
index 4a25a9b..3b34a03 100644
--- a/unsupported/test/GPU/cusolver_svd.cpp
+++ b/contrib/test/GPU/cusolver_svd.cpp
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/SVD>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include "./gpu_test_helpers.h"
 
diff --git a/unsupported/test/GPU/cusparse_spmv.cpp b/contrib/test/GPU/cusparse_spmv.cpp
similarity index 99%
rename from unsupported/test/GPU/cusparse_spmv.cpp
rename to contrib/test/GPU/cusparse_spmv.cpp
index ab1bd34..e385822 100644
--- a/unsupported/test/GPU/cusparse_spmv.cpp
+++ b/contrib/test/GPU/cusparse_spmv.cpp
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include "gpu_test_helpers.h"
 
 using namespace Eigen;
diff --git a/unsupported/test/GPU/device_buffer_pool.cpp b/contrib/test/GPU/device_buffer_pool.cpp
similarity index 98%
rename from unsupported/test/GPU/device_buffer_pool.cpp
rename to contrib/test/GPU/device_buffer_pool.cpp
index 6d2c346..e0591bd 100644
--- a/unsupported/test/GPU/device_buffer_pool.cpp
+++ b/contrib/test/GPU/device_buffer_pool.cpp
@@ -15,7 +15,7 @@
 
 #define EIGEN_USE_GPU
 #include "main.h"
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 #include <atomic>
 #include <chrono>
 #include <thread>
diff --git a/unsupported/test/GPU/device_matrix.cpp b/contrib/test/GPU/device_matrix.cpp
similarity index 99%
rename from unsupported/test/GPU/device_matrix.cpp
rename to contrib/test/GPU/device_matrix.cpp
index a7f8832..7b2a0f8 100644
--- a/unsupported/test/GPU/device_matrix.cpp
+++ b/contrib/test/GPU/device_matrix.cpp
@@ -14,7 +14,7 @@
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <Eigen/Sparse>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 #include "./gpu_test_helpers.h"
 
diff --git a/unsupported/test/GPU/device_traits.cpp b/contrib/test/GPU/device_traits.cpp
similarity index 98%
rename from unsupported/test/GPU/device_traits.cpp
rename to contrib/test/GPU/device_traits.cpp
index f2d4e1a..3e170a0 100644
--- a/unsupported/test/GPU/device_traits.cpp
+++ b/contrib/test/GPU/device_traits.cpp
@@ -7,13 +7,13 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-// Compile-time tests for the unsupported GPU type-trait surface: name-keyed
+// Compile-time tests for the contrib GPU type-trait surface: name-keyed
 // predicates plus the device_expr_traits query aliases (scalar_type_t, is_device_expr_v, trans_op).
 
 #define EIGEN_USE_GPU
 #include "main.h"
 #include <type_traits>
-#include <unsupported/Eigen/GPU>
+#include <contrib/Eigen/GPU>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/GPU/gpu_test_helpers.h b/contrib/test/GPU/gpu_test_helpers.h
similarity index 100%
rename from unsupported/test/GPU/gpu_test_helpers.h
rename to contrib/test/GPU/gpu_test_helpers.h
diff --git a/unsupported/test/NNLS.cpp b/contrib/test/NNLS.cpp
similarity index 99%
rename from unsupported/test/NNLS.cpp
rename to contrib/test/NNLS.cpp
index 6d783b1..1101310 100644
--- a/unsupported/test/NNLS.cpp
+++ b/contrib/test/NNLS.cpp
@@ -11,7 +11,7 @@
 #define EIGEN_RUNTIME_NO_MALLOC
 
 #include "main.h"
-#include <unsupported/Eigen/NNLS>
+#include <contrib/Eigen/NNLS>
 
 /// Check that 'x' solves the NNLS optimization problem `min ||A*x-b|| s.t. 0 <= x`.
 /// The \p tolerance parameter is the absolute tolerance on the gradient, A'*(A*x-b).
diff --git a/unsupported/test/NonLinearOptimization.cpp b/contrib/test/NonLinearOptimization.cpp
similarity index 99%
rename from unsupported/test/NonLinearOptimization.cpp
rename to contrib/test/NonLinearOptimization.cpp
index 16f9128..62a786e 100644
--- a/unsupported/test/NonLinearOptimization.cpp
+++ b/contrib/test/NonLinearOptimization.cpp
@@ -7,7 +7,7 @@
 #include <stdio.h>
 
 #include "main.h"
-#include <unsupported/Eigen/NonLinearOptimization>
+#include <contrib/Eigen/NonLinearOptimization>
 
 // This disables some useless Warnings on MSVC.
 // It is intended to be done for this test only.
diff --git a/unsupported/test/NumericalDiff.cpp b/contrib/test/NumericalDiff.cpp
similarity index 98%
rename from unsupported/test/NumericalDiff.cpp
rename to contrib/test/NumericalDiff.cpp
index d2ebd6a..f985d4d 100644
--- a/unsupported/test/NumericalDiff.cpp
+++ b/contrib/test/NumericalDiff.cpp
@@ -7,7 +7,7 @@
 #include <stdio.h>
 
 #include "main.h"
-#include <unsupported/Eigen/NumericalDiff>
+#include <contrib/Eigen/NumericalDiff>
 
 // Generic functor
 template <typename Scalar_, int NX = Dynamic, int NY = Dynamic>
diff --git a/unsupported/test/alignedvector3.cpp b/contrib/test/alignedvector3.cpp
similarity index 98%
rename from unsupported/test/alignedvector3.cpp
rename to contrib/test/alignedvector3.cpp
index 45ae3b2..6f885c3 100644
--- a/unsupported/test/alignedvector3.cpp
+++ b/contrib/test/alignedvector3.cpp
@@ -11,7 +11,7 @@
 #define EIGEN_NO_STATIC_ASSERT
 
 #include "main.h"
-#include <unsupported/Eigen/AlignedVector3>
+#include <contrib/Eigen/AlignedVector3>
 
 namespace Eigen {
 
diff --git a/unsupported/test/autodiff.cpp b/contrib/test/autodiff.cpp
similarity index 99%
rename from unsupported/test/autodiff.cpp
rename to contrib/test/autodiff.cpp
index 74b1266..7769154 100644
--- a/unsupported/test/autodiff.cpp
+++ b/contrib/test/autodiff.cpp
@@ -9,7 +9,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include "main.h"
-#include <unsupported/Eigen/AutoDiff>
+#include <contrib/Eigen/AutoDiff>
 
 template <typename Scalar>
 EIGEN_DONT_INLINE Scalar foo(const Scalar& x, const Scalar& y) {
diff --git a/unsupported/test/autodiff_scalar.cpp b/contrib/test/autodiff_scalar.cpp
similarity index 98%
rename from unsupported/test/autodiff_scalar.cpp
rename to contrib/test/autodiff_scalar.cpp
index 17b3dd1..b9fe84f 100644
--- a/unsupported/test/autodiff_scalar.cpp
+++ b/contrib/test/autodiff_scalar.cpp
@@ -9,7 +9,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include "main.h"
-#include <unsupported/Eigen/AutoDiff>
+#include <contrib/Eigen/AutoDiff>
 
 /*
  * In this file scalar derivations are tested for correctness.
diff --git a/unsupported/test/bessel_functions.cpp b/contrib/test/bessel_functions.cpp
similarity index 100%
rename from unsupported/test/bessel_functions.cpp
rename to contrib/test/bessel_functions.cpp
diff --git a/unsupported/test/duccfft.cpp b/contrib/test/duccfft.cpp
similarity index 100%
rename from unsupported/test/duccfft.cpp
rename to contrib/test/duccfft.cpp
diff --git a/unsupported/test/fft_test_shared.h b/contrib/test/fft_test_shared.h
similarity index 99%
rename from unsupported/test/fft_test_shared.h
rename to contrib/test/fft_test_shared.h
index ecba4c6..12e8044 100644
--- a/unsupported/test/fft_test_shared.h
+++ b/contrib/test/fft_test_shared.h
@@ -19,7 +19,7 @@
 #include "main.h"
 
 #include <thread>
-#include <unsupported/Eigen/FFT>
+#include <contrib/Eigen/FFT>
 
 template <typename T>
 inline std::complex<T> RandomCpx() {
diff --git a/unsupported/test/forward_adolc.cpp b/contrib/test/forward_adolc.cpp
similarity index 98%
rename from unsupported/test/forward_adolc.cpp
rename to contrib/test/forward_adolc.cpp
index 48df621..3ed5f1a 100644
--- a/unsupported/test/forward_adolc.cpp
+++ b/contrib/test/forward_adolc.cpp
@@ -12,7 +12,7 @@
 #include <Eigen/Dense>
 
 #define NUMBER_DIRECTIONS 16
-#include <unsupported/Eigen/AdolcForward>
+#include <contrib/Eigen/AdolcForward>
 
 template <typename Vector>
 EIGEN_DONT_INLINE typename Vector::Scalar foo(const Vector& p) {
diff --git a/unsupported/test/kronecker_product.cpp b/contrib/test/kronecker_product.cpp
similarity index 100%
rename from unsupported/test/kronecker_product.cpp
rename to contrib/test/kronecker_product.cpp
diff --git a/unsupported/test/levenberg_marquardt.cpp b/contrib/test/levenberg_marquardt.cpp
similarity index 99%
rename from unsupported/test/levenberg_marquardt.cpp
rename to contrib/test/levenberg_marquardt.cpp
index 3520800..b345c6d 100644
--- a/unsupported/test/levenberg_marquardt.cpp
+++ b/contrib/test/levenberg_marquardt.cpp
@@ -14,7 +14,7 @@
 #include <stdio.h>
 
 #include "main.h"
-#include <unsupported/Eigen/LevenbergMarquardt>
+#include <contrib/Eigen/LevenbergMarquardt>
 
 // This disables some useless Warnings on MSVC.
 // It is intended to be done for this test only.
diff --git a/unsupported/test/matrix_exponential.cpp b/contrib/test/matrix_exponential.cpp
similarity index 100%
rename from unsupported/test/matrix_exponential.cpp
rename to contrib/test/matrix_exponential.cpp
diff --git a/unsupported/test/matrix_function.cpp b/contrib/test/matrix_function.cpp
similarity index 99%
rename from unsupported/test/matrix_function.cpp
rename to contrib/test/matrix_function.cpp
index 319c4a3..86cb98a 100644
--- a/unsupported/test/matrix_function.cpp
+++ b/contrib/test/matrix_function.cpp
@@ -9,7 +9,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include "main.h"
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 
 // Returns a matrix with eigenvalues clustered around 0, 1 and 2.
 template <typename MatrixType>
diff --git a/unsupported/test/matrix_functions.h b/contrib/test/matrix_functions.h
similarity index 98%
rename from unsupported/test/matrix_functions.h
rename to contrib/test/matrix_functions.h
index b20191f..8d57aec 100644
--- a/unsupported/test/matrix_functions.h
+++ b/contrib/test/matrix_functions.h
@@ -12,7 +12,7 @@
 #define EIGEN_UNSUPPORTED_TEST_MATRIX_FUNCTIONS_H
 
 #include "main.h"
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 
 // For complex matrices, any matrix is fine.
 template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
diff --git a/unsupported/test/matrix_power.cpp b/contrib/test/matrix_power.cpp
similarity index 100%
rename from unsupported/test/matrix_power.cpp
rename to contrib/test/matrix_power.cpp
diff --git a/unsupported/test/matrix_square_root.cpp b/contrib/test/matrix_square_root.cpp
similarity index 100%
rename from unsupported/test/matrix_square_root.cpp
rename to contrib/test/matrix_square_root.cpp
diff --git a/unsupported/test/mklfft.cpp b/contrib/test/mklfft.cpp
similarity index 100%
rename from unsupported/test/mklfft.cpp
rename to contrib/test/mklfft.cpp
diff --git a/unsupported/test/mpreal_support.cpp b/contrib/test/mpreal_support.cpp
similarity index 100%
rename from unsupported/test/mpreal_support.cpp
rename to contrib/test/mpreal_support.cpp
diff --git a/unsupported/test/openglsupport.cpp b/contrib/test/openglsupport.cpp
similarity index 100%
rename from unsupported/test/openglsupport.cpp
rename to contrib/test/openglsupport.cpp
diff --git a/unsupported/test/pocketfft.cpp b/contrib/test/pocketfft.cpp
similarity index 100%
rename from unsupported/test/pocketfft.cpp
rename to contrib/test/pocketfft.cpp
diff --git a/unsupported/test/polynomialsolver.cpp b/contrib/test/polynomialsolver.cpp
similarity index 99%
rename from unsupported/test/polynomialsolver.cpp
rename to contrib/test/polynomialsolver.cpp
index 6918c32..824539f 100644
--- a/unsupported/test/polynomialsolver.cpp
+++ b/contrib/test/polynomialsolver.cpp
@@ -9,7 +9,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include "main.h"
-#include <unsupported/Eigen/Polynomials>
+#include <contrib/Eigen/Polynomials>
 #include <iostream>
 #include <algorithm>
 
diff --git a/unsupported/test/polynomialutils.cpp b/contrib/test/polynomialutils.cpp
similarity index 98%
rename from unsupported/test/polynomialutils.cpp
rename to contrib/test/polynomialutils.cpp
index d43c9f7..fbf6978 100644
--- a/unsupported/test/polynomialutils.cpp
+++ b/contrib/test/polynomialutils.cpp
@@ -9,7 +9,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include "main.h"
-#include <unsupported/Eigen/Polynomials>
+#include <contrib/Eigen/Polynomials>
 #include <iostream>
 
 using namespace std;
diff --git a/unsupported/test/sparse_extra.cpp b/contrib/test/sparse_extra.cpp
similarity index 100%
rename from unsupported/test/sparse_extra.cpp
rename to contrib/test/sparse_extra.cpp
diff --git a/unsupported/test/special_functions.cpp b/contrib/test/special_functions.cpp
similarity index 100%
rename from unsupported/test/special_functions.cpp
rename to contrib/test/special_functions.cpp
diff --git a/unsupported/test/special_packetmath.cpp b/contrib/test/special_packetmath.cpp
similarity index 100%
rename from unsupported/test/special_packetmath.cpp
rename to contrib/test/special_packetmath.cpp
diff --git a/unsupported/test/splines.cpp b/contrib/test/splines.cpp
similarity index 99%
rename from unsupported/test/splines.cpp
rename to contrib/test/splines.cpp
index 21fe423..a6cd449 100644
--- a/unsupported/test/splines.cpp
+++ b/contrib/test/splines.cpp
@@ -10,7 +10,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/Splines>
+#include <contrib/Eigen/Splines>
 
 namespace Eigen {
 
diff --git a/unsupported/test/structured_dplr.cpp b/contrib/test/structured_dplr.cpp
similarity index 99%
rename from unsupported/test/structured_dplr.cpp
rename to contrib/test/structured_dplr.cpp
index 18daae2..8382017 100644
--- a/unsupported/test/structured_dplr.cpp
+++ b/contrib/test/structured_dplr.cpp
@@ -9,7 +9,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/structured_kronecker.cpp b/contrib/test/structured_kronecker.cpp
similarity index 99%
rename from unsupported/test/structured_kronecker.cpp
rename to contrib/test/structured_kronecker.cpp
index 821547e..a1e118a 100644
--- a/unsupported/test/structured_kronecker.cpp
+++ b/contrib/test/structured_kronecker.cpp
@@ -9,7 +9,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/structured_matrices.cpp b/contrib/test/structured_matrices.cpp
similarity index 99%
rename from unsupported/test/structured_matrices.cpp
rename to contrib/test/structured_matrices.cpp
index f6a3f97..5a3ae49 100644
--- a/unsupported/test/structured_matrices.cpp
+++ b/contrib/test/structured_matrices.cpp
@@ -9,7 +9,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/structured_vandermonde.cpp b/contrib/test/structured_vandermonde.cpp
similarity index 99%
rename from unsupported/test/structured_vandermonde.cpp
rename to contrib/test/structured_vandermonde.cpp
index 43c3648..aea01a2 100644
--- a/unsupported/test/structured_vandermonde.cpp
+++ b/contrib/test/structured_vandermonde.cpp
@@ -9,7 +9,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/structured_vandermonde_int_index.cpp b/contrib/test/structured_vandermonde_int_index.cpp
similarity index 96%
rename from unsupported/test/structured_vandermonde_int_index.cpp
rename to contrib/test/structured_vandermonde_int_index.cpp
index 7897cd6..4d9cc1b 100644
--- a/unsupported/test/structured_vandermonde_int_index.cpp
+++ b/contrib/test/structured_vandermonde_int_index.cpp
@@ -7,7 +7,7 @@
 #define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
 #include "main.h"
 
-#include <unsupported/Eigen/StructuredMatrices>
+#include <contrib/Eigen/StructuredMatrices>
 
 using namespace Eigen;
 
diff --git a/unsupported/test/tensor_argmax.cpp b/contrib/test/tensor_argmax.cpp
similarity index 100%
rename from unsupported/test/tensor_argmax.cpp
rename to contrib/test/tensor_argmax.cpp
diff --git a/unsupported/test/tensor_argmax_gpu.cu b/contrib/test/tensor_argmax_gpu.cu
similarity index 99%
rename from unsupported/test/tensor_argmax_gpu.cu
rename to contrib/test/tensor_argmax_gpu.cu
index 1b17ce9..f944b50 100644
--- a/unsupported/test/tensor_argmax_gpu.cu
+++ b/contrib/test/tensor_argmax_gpu.cu
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_argmax_sycl.cpp b/contrib/test/tensor_argmax_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_argmax_sycl.cpp
rename to contrib/test/tensor_argmax_sycl.cpp
index a2037d8..bc19af5 100644
--- a/unsupported/test/tensor_argmax_sycl.cpp
+++ b/contrib/test/tensor_argmax_sycl.cpp
@@ -20,7 +20,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_assign.cpp b/contrib/test/tensor_assign.cpp
similarity index 100%
rename from unsupported/test/tensor_assign.cpp
rename to contrib/test/tensor_assign.cpp
diff --git a/unsupported/test/tensor_block_access.cpp b/contrib/test/tensor_block_access.cpp
similarity index 100%
rename from unsupported/test/tensor_block_access.cpp
rename to contrib/test/tensor_block_access.cpp
diff --git a/unsupported/test/tensor_block_eval.cpp b/contrib/test/tensor_block_eval.cpp
similarity index 100%
rename from unsupported/test/tensor_block_eval.cpp
rename to contrib/test/tensor_block_eval.cpp
diff --git a/unsupported/test/tensor_block_io.cpp b/contrib/test/tensor_block_io.cpp
similarity index 100%
rename from unsupported/test/tensor_block_io.cpp
rename to contrib/test/tensor_block_io.cpp
diff --git a/unsupported/test/tensor_broadcast_sycl.cpp b/contrib/test/tensor_broadcast_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_broadcast_sycl.cpp
rename to contrib/test/tensor_broadcast_sycl.cpp
index 422fed6..5d1f684 100644
--- a/unsupported/test/tensor_broadcast_sycl.cpp
+++ b/contrib/test/tensor_broadcast_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_broadcasting.cpp b/contrib/test/tensor_broadcasting.cpp
similarity index 100%
rename from unsupported/test/tensor_broadcasting.cpp
rename to contrib/test/tensor_broadcasting.cpp
diff --git a/unsupported/test/tensor_builtins_sycl.cpp b/contrib/test/tensor_builtins_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_builtins_sycl.cpp
rename to contrib/test/tensor_builtins_sycl.cpp
index 91f34d0..9fdb069 100644
--- a/unsupported/test/tensor_builtins_sycl.cpp
+++ b/contrib/test/tensor_builtins_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_cast_float16_gpu.cu b/contrib/test/tensor_cast_float16_gpu.cu
similarity index 98%
rename from unsupported/test/tensor_cast_float16_gpu.cu
rename to contrib/test/tensor_cast_float16_gpu.cu
index ba0bb5c..530eb48 100644
--- a/unsupported/test/tensor_cast_float16_gpu.cu
+++ b/contrib/test/tensor_cast_float16_gpu.cu
@@ -15,7 +15,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_casts.cpp b/contrib/test/tensor_casts.cpp
similarity index 100%
rename from unsupported/test/tensor_casts.cpp
rename to contrib/test/tensor_casts.cpp
diff --git a/unsupported/test/tensor_chipping.cpp b/contrib/test/tensor_chipping.cpp
similarity index 100%
rename from unsupported/test/tensor_chipping.cpp
rename to contrib/test/tensor_chipping.cpp
diff --git a/unsupported/test/tensor_chipping_sycl.cpp b/contrib/test/tensor_chipping_sycl.cpp
similarity index 100%
rename from unsupported/test/tensor_chipping_sycl.cpp
rename to contrib/test/tensor_chipping_sycl.cpp
diff --git a/unsupported/test/tensor_comparisons.cpp b/contrib/test/tensor_comparisons.cpp
similarity index 100%
rename from unsupported/test/tensor_comparisons.cpp
rename to contrib/test/tensor_comparisons.cpp
diff --git a/unsupported/test/tensor_complex_cwise_ops_gpu.cu b/contrib/test/tensor_complex_cwise_ops_gpu.cu
similarity index 98%
rename from unsupported/test/tensor_complex_cwise_ops_gpu.cu
rename to contrib/test/tensor_complex_cwise_ops_gpu.cu
index 52a2d1c..f99440b 100644
--- a/unsupported/test/tensor_complex_cwise_ops_gpu.cu
+++ b/contrib/test/tensor_complex_cwise_ops_gpu.cu
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_complex_gpu.cu b/contrib/test/tensor_complex_gpu.cu
similarity index 99%
rename from unsupported/test/tensor_complex_gpu.cu
rename to contrib/test/tensor_complex_gpu.cu
index 43bf3c5..3777383 100644
--- a/unsupported/test/tensor_complex_gpu.cu
+++ b/contrib/test/tensor_complex_gpu.cu
@@ -13,7 +13,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_concatenation.cpp b/contrib/test/tensor_concatenation.cpp
similarity index 100%
rename from unsupported/test/tensor_concatenation.cpp
rename to contrib/test/tensor_concatenation.cpp
diff --git a/unsupported/test/tensor_concatenation_sycl.cpp b/contrib/test/tensor_concatenation_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_concatenation_sycl.cpp
rename to contrib/test/tensor_concatenation_sycl.cpp
index 7629432..31cd01f 100644
--- a/unsupported/test/tensor_concatenation_sycl.cpp
+++ b/contrib/test/tensor_concatenation_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_const.cpp b/contrib/test/tensor_const.cpp
similarity index 100%
rename from unsupported/test/tensor_const.cpp
rename to contrib/test/tensor_const.cpp
diff --git a/unsupported/test/tensor_contract_gpu.cu b/contrib/test/tensor_contract_gpu.cu
similarity index 92%
rename from unsupported/test/tensor_contract_gpu.cu
rename to contrib/test/tensor_contract_gpu.cu
index 1db50b1..17e02fa 100644
--- a/unsupported/test/tensor_contract_gpu.cu
+++ b/contrib/test/tensor_contract_gpu.cu
@@ -16,7 +16,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 typedef Tensor<float, 1>::DimensionPair DimPair;
@@ -50,9 +50,9 @@
   Eigen::GpuStreamDevice stream;
   Eigen::GpuDevice gpu_device(&stream);
 
-  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout> > gpu_t_left(d_t_left, Eigen::array<int, 2>{m_size, k_size});
-  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout> > gpu_t_right(d_t_right, Eigen::array<int, 2>{k_size, n_size});
-  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout> > gpu_t_result(d_t_result, Eigen::array<int, 2>{m_size, n_size});
+  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout>> gpu_t_left(d_t_left, Eigen::array<int, 2>{m_size, k_size});
+  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout>> gpu_t_right(d_t_right, Eigen::array<int, 2>{k_size, n_size});
+  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout>> gpu_t_result(d_t_result, Eigen::array<int, 2>{m_size, n_size});
 
   gpu_t_result.device(gpu_device) = gpu_t_left.contract(gpu_t_right, dims);
   t_result = t_left.contract(t_right, dims);
@@ -150,10 +150,9 @@
   Eigen::GpuStreamDevice stream;
   Eigen::GpuDevice gpu_device(&stream);
 
-  Eigen::TensorMap<Eigen::Tensor<double, 2, DataLayout> > gpu_t_left(d_t_left, Eigen::array<int, 2>{m_size, k_size});
-  Eigen::TensorMap<Eigen::Tensor<double, 2, DataLayout> > gpu_t_right(d_t_right, Eigen::array<int, 2>{k_size, n_size});
-  Eigen::TensorMap<Eigen::Tensor<double, 2, DataLayout> > gpu_t_result(d_t_result,
-                                                                       Eigen::array<int, 2>{m_size, n_size});
+  Eigen::TensorMap<Eigen::Tensor<double, 2, DataLayout>> gpu_t_left(d_t_left, Eigen::array<int, 2>{m_size, k_size});
+  Eigen::TensorMap<Eigen::Tensor<double, 2, DataLayout>> gpu_t_right(d_t_right, Eigen::array<int, 2>{k_size, n_size});
+  Eigen::TensorMap<Eigen::Tensor<double, 2, DataLayout>> gpu_t_result(d_t_result, Eigen::array<int, 2>{m_size, n_size});
 
   gpu_t_result.device(gpu_device) = gpu_t_left.contract(gpu_t_right, dims);
   t_result = t_left.contract(t_right, dims);
@@ -208,9 +207,9 @@
   Eigen::GpuStreamDevice stream;
   Eigen::GpuDevice gpu_device(&stream);
 
-  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout> > gpu_t_left(d_t_left, m_size, k_size);
-  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout> > gpu_t_right(d_t_right, k_size, n_size);
-  Eigen::TensorMap<Eigen::Tensor<float, 0, DataLayout> > gpu_t_result(d_t_result);
+  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout>> gpu_t_left(d_t_left, m_size, k_size);
+  Eigen::TensorMap<Eigen::Tensor<float, 2, DataLayout>> gpu_t_right(d_t_right, k_size, n_size);
+  Eigen::TensorMap<Eigen::Tensor<float, 0, DataLayout>> gpu_t_result(d_t_result);
 
   gpu_t_result.device(gpu_device) = gpu_t_left.contract(gpu_t_right, dims);
   t_result = t_left.contract(t_right, dims);
diff --git a/unsupported/test/tensor_contract_sycl.cpp b/contrib/test/tensor_contract_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_contract_sycl.cpp
rename to contrib/test/tensor_contract_sycl.cpp
index 8d79bec..fc0be05 100644
--- a/unsupported/test/tensor_contract_sycl.cpp
+++ b/contrib/test/tensor_contract_sycl.cpp
@@ -25,7 +25,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_contraction.cpp b/contrib/test/tensor_contraction.cpp
similarity index 100%
rename from unsupported/test/tensor_contraction.cpp
rename to contrib/test/tensor_contraction.cpp
diff --git a/unsupported/test/tensor_convolution.cpp b/contrib/test/tensor_convolution.cpp
similarity index 100%
rename from unsupported/test/tensor_convolution.cpp
rename to contrib/test/tensor_convolution.cpp
diff --git a/unsupported/test/tensor_convolution_sycl.cpp b/contrib/test/tensor_convolution_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_convolution_sycl.cpp
rename to contrib/test/tensor_convolution_sycl.cpp
index fc5da24..8366310 100644
--- a/unsupported/test/tensor_convolution_sycl.cpp
+++ b/contrib/test/tensor_convolution_sycl.cpp
@@ -23,7 +23,7 @@
 #include <ctime>
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 #include <iomanip>
 
 using Eigen::array;
diff --git a/unsupported/test/tensor_cost_model.cpp b/contrib/test/tensor_cost_model.cpp
similarity index 100%
rename from unsupported/test/tensor_cost_model.cpp
rename to contrib/test/tensor_cost_model.cpp
diff --git a/unsupported/test/tensor_custom_index.cpp b/contrib/test/tensor_custom_index.cpp
similarity index 100%
rename from unsupported/test/tensor_custom_index.cpp
rename to contrib/test/tensor_custom_index.cpp
diff --git a/unsupported/test/tensor_custom_op.cpp b/contrib/test/tensor_custom_op.cpp
similarity index 100%
rename from unsupported/test/tensor_custom_op.cpp
rename to contrib/test/tensor_custom_op.cpp
diff --git a/unsupported/test/tensor_custom_op_sycl.cpp b/contrib/test/tensor_custom_op_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_custom_op_sycl.cpp
rename to contrib/test/tensor_custom_op_sycl.cpp
index 7d089a1..de5740a 100644
--- a/unsupported/test/tensor_custom_op_sycl.cpp
+++ b/contrib/test/tensor_custom_op_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 template <typename TensorType>
diff --git a/unsupported/test/tensor_device.cu b/contrib/test/tensor_device.cu
similarity index 99%
rename from unsupported/test/tensor_device.cu
rename to contrib/test/tensor_device.cu
index eee34b2..5a36dec 100644
--- a/unsupported/test/tensor_device.cu
+++ b/contrib/test/tensor_device.cu
@@ -16,7 +16,7 @@
 
 #include "main.h"
 #include "OffByOneScalar.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::RowMajor;
 using Eigen::Tensor;
diff --git a/unsupported/test/tensor_device_sycl.cpp b/contrib/test/tensor_device_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_device_sycl.cpp
rename to contrib/test/tensor_device_sycl.cpp
index 760a7c5..77b6d82 100644
--- a/unsupported/test/tensor_device_sycl.cpp
+++ b/contrib/test/tensor_device_sycl.cpp
@@ -20,7 +20,7 @@
 
 #include "main.h"
 #include "OffByOneScalar.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 #include <stdint.h>
 #include <iostream>
 
diff --git a/unsupported/test/tensor_dimension.cpp b/contrib/test/tensor_dimension.cpp
similarity index 100%
rename from unsupported/test/tensor_dimension.cpp
rename to contrib/test/tensor_dimension.cpp
diff --git a/unsupported/test/tensor_empty.cpp b/contrib/test/tensor_empty.cpp
similarity index 100%
rename from unsupported/test/tensor_empty.cpp
rename to contrib/test/tensor_empty.cpp
diff --git a/unsupported/test/tensor_executor.cpp b/contrib/test/tensor_executor.cpp
similarity index 100%
rename from unsupported/test/tensor_executor.cpp
rename to contrib/test/tensor_executor.cpp
diff --git a/unsupported/test/tensor_expr.cpp b/contrib/test/tensor_expr.cpp
similarity index 100%
rename from unsupported/test/tensor_expr.cpp
rename to contrib/test/tensor_expr.cpp
diff --git a/unsupported/test/tensor_fft.cpp b/contrib/test/tensor_fft.cpp
similarity index 100%
rename from unsupported/test/tensor_fft.cpp
rename to contrib/test/tensor_fft.cpp
diff --git a/unsupported/test/tensor_fixed_size.cpp b/contrib/test/tensor_fixed_size.cpp
similarity index 100%
rename from unsupported/test/tensor_fixed_size.cpp
rename to contrib/test/tensor_fixed_size.cpp
diff --git a/unsupported/test/tensor_forced_eval.cpp b/contrib/test/tensor_forced_eval.cpp
similarity index 100%
rename from unsupported/test/tensor_forced_eval.cpp
rename to contrib/test/tensor_forced_eval.cpp
diff --git a/unsupported/test/tensor_forced_eval_sycl.cpp b/contrib/test/tensor_forced_eval_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_forced_eval_sycl.cpp
rename to contrib/test/tensor_forced_eval_sycl.cpp
index 1ba37dc..71108c8 100644
--- a/unsupported/test/tensor_forced_eval_sycl.cpp
+++ b/contrib/test/tensor_forced_eval_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 template <typename DataType, int DataLayout, typename IndexType>
diff --git a/unsupported/test/tensor_generator.cpp b/contrib/test/tensor_generator.cpp
similarity index 100%
rename from unsupported/test/tensor_generator.cpp
rename to contrib/test/tensor_generator.cpp
diff --git a/unsupported/test/tensor_generator_sycl.cpp b/contrib/test/tensor_generator_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_generator_sycl.cpp
rename to contrib/test/tensor_generator_sycl.cpp
index b0cdb65..6439afd 100644
--- a/unsupported/test/tensor_generator_sycl.cpp
+++ b/contrib/test/tensor_generator_sycl.cpp
@@ -20,7 +20,7 @@
 static const float error_threshold = 1e-8f;
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 struct Generator1D {
diff --git a/unsupported/test/tensor_gpu.cu b/contrib/test/tensor_gpu.cu
similarity index 99%
rename from unsupported/test/tensor_gpu.cu
rename to contrib/test/tensor_gpu.cu
index 4a24ff4..981a53c 100644
--- a/unsupported/test/tensor_gpu.cu
+++ b/contrib/test/tensor_gpu.cu
@@ -14,7 +14,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_ifft.cpp b/contrib/test/tensor_ifft.cpp
similarity index 100%
rename from unsupported/test/tensor_ifft.cpp
rename to contrib/test/tensor_ifft.cpp
diff --git a/unsupported/test/tensor_image_op_sycl.cpp b/contrib/test/tensor_image_op_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_image_op_sycl.cpp
rename to contrib/test/tensor_image_op_sycl.cpp
index 0896669..80df57e 100644
--- a/unsupported/test/tensor_image_op_sycl.cpp
+++ b/contrib/test/tensor_image_op_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_image_patch.cpp b/contrib/test/tensor_image_patch.cpp
similarity index 100%
rename from unsupported/test/tensor_image_patch.cpp
rename to contrib/test/tensor_image_patch.cpp
diff --git a/unsupported/test/tensor_image_patch_sycl.cpp b/contrib/test/tensor_image_patch_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_image_patch_sycl.cpp
rename to contrib/test/tensor_image_patch_sycl.cpp
index a082518..de540c5 100644
--- a/unsupported/test/tensor_image_patch_sycl.cpp
+++ b/contrib/test/tensor_image_patch_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 static const int DataLayout = ColMajor;
diff --git a/unsupported/test/tensor_index_list.cpp b/contrib/test/tensor_index_list.cpp
similarity index 100%
rename from unsupported/test/tensor_index_list.cpp
rename to contrib/test/tensor_index_list.cpp
diff --git a/unsupported/test/tensor_inflation.cpp b/contrib/test/tensor_inflation.cpp
similarity index 100%
rename from unsupported/test/tensor_inflation.cpp
rename to contrib/test/tensor_inflation.cpp
diff --git a/unsupported/test/tensor_inflation_sycl.cpp b/contrib/test/tensor_inflation_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_inflation_sycl.cpp
rename to contrib/test/tensor_inflation_sycl.cpp
index d9b7290..2a800ef 100644
--- a/unsupported/test/tensor_inflation_sycl.cpp
+++ b/contrib/test/tensor_inflation_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_intdiv.cpp b/contrib/test/tensor_intdiv.cpp
similarity index 100%
rename from unsupported/test/tensor_intdiv.cpp
rename to contrib/test/tensor_intdiv.cpp
diff --git a/unsupported/test/tensor_io.cpp b/contrib/test/tensor_io.cpp
similarity index 100%
rename from unsupported/test/tensor_io.cpp
rename to contrib/test/tensor_io.cpp
diff --git a/unsupported/test/tensor_layout_swap.cpp b/contrib/test/tensor_layout_swap.cpp
similarity index 100%
rename from unsupported/test/tensor_layout_swap.cpp
rename to contrib/test/tensor_layout_swap.cpp
diff --git a/unsupported/test/tensor_layout_swap_sycl.cpp b/contrib/test/tensor_layout_swap_sycl.cpp
similarity index 100%
rename from unsupported/test/tensor_layout_swap_sycl.cpp
rename to contrib/test/tensor_layout_swap_sycl.cpp
diff --git a/unsupported/test/tensor_lvalue.cpp b/contrib/test/tensor_lvalue.cpp
similarity index 100%
rename from unsupported/test/tensor_lvalue.cpp
rename to contrib/test/tensor_lvalue.cpp
diff --git a/unsupported/test/tensor_map.cpp b/contrib/test/tensor_map.cpp
similarity index 100%
rename from unsupported/test/tensor_map.cpp
rename to contrib/test/tensor_map.cpp
diff --git a/unsupported/test/tensor_math.cpp b/contrib/test/tensor_math.cpp
similarity index 100%
rename from unsupported/test/tensor_math.cpp
rename to contrib/test/tensor_math.cpp
diff --git a/unsupported/test/tensor_math_sycl.cpp b/contrib/test/tensor_math_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_math_sycl.cpp
rename to contrib/test/tensor_math_sycl.cpp
index 39dbdbf..73e7859 100644
--- a/unsupported/test/tensor_math_sycl.cpp
+++ b/contrib/test/tensor_math_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_mixed_indices.cpp b/contrib/test/tensor_mixed_indices.cpp
similarity index 100%
rename from unsupported/test/tensor_mixed_indices.cpp
rename to contrib/test/tensor_mixed_indices.cpp
diff --git a/unsupported/test/tensor_morphing.cpp b/contrib/test/tensor_morphing.cpp
similarity index 100%
rename from unsupported/test/tensor_morphing.cpp
rename to contrib/test/tensor_morphing.cpp
diff --git a/unsupported/test/tensor_morphing_sycl.cpp b/contrib/test/tensor_morphing_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_morphing_sycl.cpp
rename to contrib/test/tensor_morphing_sycl.cpp
index 0f4017f..5b66b24 100644
--- a/unsupported/test/tensor_morphing_sycl.cpp
+++ b/contrib/test/tensor_morphing_sycl.cpp
@@ -20,7 +20,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_move.cpp b/contrib/test/tensor_move.cpp
similarity index 100%
rename from unsupported/test/tensor_move.cpp
rename to contrib/test/tensor_move.cpp
diff --git a/unsupported/test/tensor_notification.cpp b/contrib/test/tensor_notification.cpp
similarity index 100%
rename from unsupported/test/tensor_notification.cpp
rename to contrib/test/tensor_notification.cpp
diff --git a/unsupported/test/tensor_of_bfloat16_gpu.cu b/contrib/test/tensor_of_bfloat16_gpu.cu
similarity index 99%
rename from unsupported/test/tensor_of_bfloat16_gpu.cu
rename to contrib/test/tensor_of_bfloat16_gpu.cu
index 2b6fea2..fc1cc27 100644
--- a/unsupported/test/tensor_of_bfloat16_gpu.cu
+++ b/contrib/test/tensor_of_bfloat16_gpu.cu
@@ -15,7 +15,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_of_complex.cpp b/contrib/test/tensor_of_complex.cpp
similarity index 100%
rename from unsupported/test/tensor_of_complex.cpp
rename to contrib/test/tensor_of_complex.cpp
diff --git a/unsupported/test/tensor_of_const_values.cpp b/contrib/test/tensor_of_const_values.cpp
similarity index 100%
rename from unsupported/test/tensor_of_const_values.cpp
rename to contrib/test/tensor_of_const_values.cpp
diff --git a/unsupported/test/tensor_of_float16_gpu.cu b/contrib/test/tensor_of_float16_gpu.cu
similarity index 99%
rename from unsupported/test/tensor_of_float16_gpu.cu
rename to contrib/test/tensor_of_float16_gpu.cu
index 22483ed..46e2862 100644
--- a/unsupported/test/tensor_of_float16_gpu.cu
+++ b/contrib/test/tensor_of_float16_gpu.cu
@@ -15,7 +15,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 
diff --git a/unsupported/test/tensor_of_float16_sycl.cpp b/contrib/test/tensor_of_float16_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_of_float16_sycl.cpp
rename to contrib/test/tensor_of_float16_sycl.cpp
index 5259649..cede148 100644
--- a/unsupported/test/tensor_of_float16_sycl.cpp
+++ b/contrib/test/tensor_of_float16_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_SYCL_HALF_SUPPORT
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::SyclDevice;
 using Eigen::Tensor;
diff --git a/unsupported/test/tensor_of_strings.cpp b/contrib/test/tensor_of_strings.cpp
similarity index 100%
rename from unsupported/test/tensor_of_strings.cpp
rename to contrib/test/tensor_of_strings.cpp
diff --git a/unsupported/test/tensor_padding.cpp b/contrib/test/tensor_padding.cpp
similarity index 100%
rename from unsupported/test/tensor_padding.cpp
rename to contrib/test/tensor_padding.cpp
diff --git a/unsupported/test/tensor_padding_sycl.cpp b/contrib/test/tensor_padding_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_padding_sycl.cpp
rename to contrib/test/tensor_padding_sycl.cpp
index d78a34f..93e7727 100644
--- a/unsupported/test/tensor_padding_sycl.cpp
+++ b/contrib/test/tensor_padding_sycl.cpp
@@ -20,7 +20,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_patch.cpp b/contrib/test/tensor_patch.cpp
similarity index 100%
rename from unsupported/test/tensor_patch.cpp
rename to contrib/test/tensor_patch.cpp
diff --git a/unsupported/test/tensor_patch_sycl.cpp b/contrib/test/tensor_patch_sycl.cpp
similarity index 100%
rename from unsupported/test/tensor_patch_sycl.cpp
rename to contrib/test/tensor_patch_sycl.cpp
diff --git a/unsupported/test/tensor_random.cpp b/contrib/test/tensor_random.cpp
similarity index 100%
rename from unsupported/test/tensor_random.cpp
rename to contrib/test/tensor_random.cpp
diff --git a/unsupported/test/tensor_random_gpu.cu b/contrib/test/tensor_random_gpu.cu
similarity index 100%
rename from unsupported/test/tensor_random_gpu.cu
rename to contrib/test/tensor_random_gpu.cu
diff --git a/unsupported/test/tensor_random_sycl.cpp b/contrib/test/tensor_random_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_random_sycl.cpp
rename to contrib/test/tensor_random_sycl.cpp
index 6e85e9c..72bb147 100644
--- a/unsupported/test/tensor_random_sycl.cpp
+++ b/contrib/test/tensor_random_sycl.cpp
@@ -18,7 +18,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 template <typename DataType, int DataLayout, typename IndexType>
 static void test_sycl_random_uniform(const Eigen::SyclDevice& sycl_device) {
diff --git a/unsupported/test/tensor_reduction.cpp b/contrib/test/tensor_reduction.cpp
similarity index 100%
rename from unsupported/test/tensor_reduction.cpp
rename to contrib/test/tensor_reduction.cpp
diff --git a/unsupported/test/tensor_reduction_gpu.cu b/contrib/test/tensor_reduction_gpu.cu
similarity index 98%
rename from unsupported/test/tensor_reduction_gpu.cu
rename to contrib/test/tensor_reduction_gpu.cu
index a8b0c45..2b49e08 100644
--- a/unsupported/test/tensor_reduction_gpu.cu
+++ b/contrib/test/tensor_reduction_gpu.cu
@@ -14,7 +14,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 template <typename Type, int DataLayout>
 static void test_full_reductions() {
diff --git a/unsupported/test/tensor_reduction_sycl.cpp b/contrib/test/tensor_reduction_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_reduction_sycl.cpp
rename to contrib/test/tensor_reduction_sycl.cpp
index afa7773..b4ce774 100644
--- a/unsupported/test/tensor_reduction_sycl.cpp
+++ b/contrib/test/tensor_reduction_sycl.cpp
@@ -20,7 +20,7 @@
 
 #include "main.h"
 
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 template <typename DataType, int DataLayout, typename IndexType>
 static void test_full_reductions_sum_sycl(const Eigen::SyclDevice& sycl_device) {
diff --git a/unsupported/test/tensor_ref.cpp b/contrib/test/tensor_ref.cpp
similarity index 100%
rename from unsupported/test/tensor_ref.cpp
rename to contrib/test/tensor_ref.cpp
diff --git a/unsupported/test/tensor_reinclude.cpp b/contrib/test/tensor_reinclude.cpp
similarity index 100%
rename from unsupported/test/tensor_reinclude.cpp
rename to contrib/test/tensor_reinclude.cpp
diff --git a/unsupported/test/tensor_reverse.cpp b/contrib/test/tensor_reverse.cpp
similarity index 100%
rename from unsupported/test/tensor_reverse.cpp
rename to contrib/test/tensor_reverse.cpp
diff --git a/unsupported/test/tensor_reverse_sycl.cpp b/contrib/test/tensor_reverse_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_reverse_sycl.cpp
rename to contrib/test/tensor_reverse_sycl.cpp
index 3597687..579991a 100644
--- a/unsupported/test/tensor_reverse_sycl.cpp
+++ b/contrib/test/tensor_reverse_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 template <typename DataType, int DataLayout, typename IndexType>
 static void test_simple_reverse(const Eigen::SyclDevice& sycl_device) {
diff --git a/unsupported/test/tensor_roll.cpp b/contrib/test/tensor_roll.cpp
similarity index 100%
rename from unsupported/test/tensor_roll.cpp
rename to contrib/test/tensor_roll.cpp
diff --git a/unsupported/test/tensor_roundings.cpp b/contrib/test/tensor_roundings.cpp
similarity index 100%
rename from unsupported/test/tensor_roundings.cpp
rename to contrib/test/tensor_roundings.cpp
diff --git a/unsupported/test/tensor_scan.cpp b/contrib/test/tensor_scan.cpp
similarity index 100%
rename from unsupported/test/tensor_scan.cpp
rename to contrib/test/tensor_scan.cpp
diff --git a/unsupported/test/tensor_scan_gpu.cu b/contrib/test/tensor_scan_gpu.cu
similarity index 98%
rename from unsupported/test/tensor_scan_gpu.cu
rename to contrib/test/tensor_scan_gpu.cu
index c30c9f5..f586c08 100644
--- a/unsupported/test/tensor_scan_gpu.cu
+++ b/contrib/test/tensor_scan_gpu.cu
@@ -15,7 +15,7 @@
 #define EIGEN_USE_GPU
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 typedef Tensor<float, 1>::DimensionPair DimPair;
diff --git a/unsupported/test/tensor_scan_sycl.cpp b/contrib/test/tensor_scan_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_scan_sycl.cpp
rename to contrib/test/tensor_scan_sycl.cpp
index 2971c0c..79518b6 100644
--- a/unsupported/test/tensor_scan_sycl.cpp
+++ b/contrib/test/tensor_scan_sycl.cpp
@@ -18,7 +18,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 typedef Tensor<float, 1>::DimensionPair DimPair;
diff --git a/unsupported/test/tensor_shuffling.cpp b/contrib/test/tensor_shuffling.cpp
similarity index 100%
rename from unsupported/test/tensor_shuffling.cpp
rename to contrib/test/tensor_shuffling.cpp
diff --git a/unsupported/test/tensor_shuffling_sycl.cpp b/contrib/test/tensor_shuffling_sycl.cpp
similarity index 98%
rename from unsupported/test/tensor_shuffling_sycl.cpp
rename to contrib/test/tensor_shuffling_sycl.cpp
index 907cbe2..fe45e1f 100644
--- a/unsupported/test/tensor_shuffling_sycl.cpp
+++ b/contrib/test/tensor_shuffling_sycl.cpp
@@ -20,7 +20,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_simple.cpp b/contrib/test/tensor_simple.cpp
similarity index 100%
rename from unsupported/test/tensor_simple.cpp
rename to contrib/test/tensor_simple.cpp
diff --git a/unsupported/test/tensor_special_members.cpp b/contrib/test/tensor_special_members.cpp
similarity index 100%
rename from unsupported/test/tensor_special_members.cpp
rename to contrib/test/tensor_special_members.cpp
diff --git a/unsupported/test/tensor_striding.cpp b/contrib/test/tensor_striding.cpp
similarity index 100%
rename from unsupported/test/tensor_striding.cpp
rename to contrib/test/tensor_striding.cpp
diff --git a/unsupported/test/tensor_striding_sycl.cpp b/contrib/test/tensor_striding_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_striding_sycl.cpp
rename to contrib/test/tensor_striding_sycl.cpp
index c7f4185..95097eb 100644
--- a/unsupported/test/tensor_striding_sycl.cpp
+++ b/contrib/test/tensor_striding_sycl.cpp
@@ -23,7 +23,7 @@
 #include <ctime>
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_sugar.cpp b/contrib/test/tensor_sugar.cpp
similarity index 100%
rename from unsupported/test/tensor_sugar.cpp
rename to contrib/test/tensor_sugar.cpp
diff --git a/unsupported/test/tensor_sycl.cpp b/contrib/test/tensor_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_sycl.cpp
rename to contrib/test/tensor_sycl.cpp
index f1b77bd..0b6f383 100644
--- a/unsupported/test/tensor_sycl.cpp
+++ b/contrib/test/tensor_sycl.cpp
@@ -20,7 +20,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::array;
 using Eigen::SyclDevice;
diff --git a/unsupported/test/tensor_symmetry.cpp b/contrib/test/tensor_symmetry.cpp
similarity index 100%
rename from unsupported/test/tensor_symmetry.cpp
rename to contrib/test/tensor_symmetry.cpp
diff --git a/unsupported/test/tensor_thread_local.cpp b/contrib/test/tensor_thread_local.cpp
similarity index 100%
rename from unsupported/test/tensor_thread_local.cpp
rename to contrib/test/tensor_thread_local.cpp
diff --git a/unsupported/test/tensor_thread_pool.cpp b/contrib/test/tensor_thread_pool.cpp
similarity index 100%
rename from unsupported/test/tensor_thread_pool.cpp
rename to contrib/test/tensor_thread_pool.cpp
diff --git a/unsupported/test/tensor_trace.cpp b/contrib/test/tensor_trace.cpp
similarity index 100%
rename from unsupported/test/tensor_trace.cpp
rename to contrib/test/tensor_trace.cpp
diff --git a/unsupported/test/tensor_uint128.cpp b/contrib/test/tensor_uint128.cpp
similarity index 100%
rename from unsupported/test/tensor_uint128.cpp
rename to contrib/test/tensor_uint128.cpp
diff --git a/unsupported/test/tensor_volume_patch.cpp b/contrib/test/tensor_volume_patch.cpp
similarity index 100%
rename from unsupported/test/tensor_volume_patch.cpp
rename to contrib/test/tensor_volume_patch.cpp
diff --git a/unsupported/test/tensor_volume_patch_sycl.cpp b/contrib/test/tensor_volume_patch_sycl.cpp
similarity index 99%
rename from unsupported/test/tensor_volume_patch_sycl.cpp
rename to contrib/test/tensor_volume_patch_sycl.cpp
index bb597a4..28310a4 100644
--- a/unsupported/test/tensor_volume_patch_sycl.cpp
+++ b/contrib/test/tensor_volume_patch_sycl.cpp
@@ -19,7 +19,7 @@
 #define EIGEN_USE_SYCL
 
 #include "main.h"
-#include <unsupported/Eigen/Tensor>
+#include <contrib/Eigen/Tensor>
 
 using Eigen::Tensor;
 static const int DataLayout = ColMajor;
diff --git a/doc/B01_Experimental.dox b/doc/B01_Experimental.dox
index f538df8..13ddef0 100644
--- a/doc/B01_Experimental.dox
+++ b/doc/B01_Experimental.dox
@@ -21,12 +21,12 @@
 \li Features whose documentation carries the explicit warning "This is not considered to be part of
     the stable public API yet", which links to this page.
 \li Everything in the \c Eigen::internal namespace, and the private implementation headers under
-    <tt>Eigen/src/</tt> and <tt>unsupported/Eigen/src/</tt>. Include the public module headers such
+    <tt>Eigen/src/</tt> and <tt>contrib/Eigen/src/</tt>. Include the public module headers such
     as <tt><Eigen/Core></tt> instead; names not reachable through them are implementation details,
     even where a header does not mechanically enforce this.
-\li The modules under <a href="unsupported/index.html"><tt>unsupported/Eigen/</tt></a>. These are
+\li The modules under <a href="contrib/index.html"><tt>contrib/Eigen/</tt></a>. These are
     contributed modules maintained with looser API-stability guarantees than the main library.
-    "Unsupported" does not mean low quality or low usage — the Tensor module, for instance, is a
+    "Contrib" does not mean low quality or low usage — the Tensor module, for instance, is a
     foundational dependency of TensorFlow — but their APIs may evolve between minor releases.
 
 Undocumented behavior of otherwise stable classes (for example, the exact layout of a
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 0b3a89a..9a4f8cd 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -40,16 +40,16 @@
   ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
 )
 
-set(EIGEN_DOXY_PROJECT_NAME             "Eigen-unsupported")
-set(EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX  "/unsupported")
-set(EIGEN_DOXY_INPUT                    "\"${Eigen_SOURCE_DIR}/unsupported/doc\" \"${Eigen_SOURCE_DIR}/unsupported/Eigen\"")
+set(EIGEN_DOXY_PROJECT_NAME             "Eigen-Contrib")
+set(EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX  "/contrib")
+set(EIGEN_DOXY_INPUT                    "\"${Eigen_SOURCE_DIR}/contrib/doc\" \"${Eigen_SOURCE_DIR}/contrib/Eigen\"")
 set(EIGEN_DOXY_HTML_COLORSTYLE_HUE      "0")
 set(EIGEN_DOXY_TAGFILES                 "\"${Eigen_BINARY_DIR}/doc/Eigen.doxytags=..\"")
 #set(EIGEN_DOXY_TAGFILES                 "")
 
 configure_file(
   ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
-  ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-unsupported
+  ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-contrib
 )
 
 configure_file(
@@ -68,8 +68,8 @@
 )
 
 configure_file(
-  ${Eigen_SOURCE_DIR}/unsupported/doc/eigendoxy_layout.xml.in
-  ${Eigen_BINARY_DIR}/doc/unsupported/eigendoxy_layout.xml
+  ${Eigen_SOURCE_DIR}/contrib/doc/eigendoxy_layout.xml.in
+  ${Eigen_BINARY_DIR}/doc/contrib/eigendoxy_layout.xml
 )
 
 set(examples_targets "")
@@ -94,30 +94,30 @@
 )
 
 add_custom_target(
-  doc-unsupported-prerequisites
+  doc-contrib-prerequisites
   ALL
-  COMMAND ${CMAKE_COMMAND} -E make_directory ${Eigen_BINARY_DIR}/doc/html/unsupported
-  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Eigen_Silly_Professor_64x64.png  ${CMAKE_CURRENT_BINARY_DIR}/html/unsupported/
-  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/ftv2pnode.png                    ${CMAKE_CURRENT_BINARY_DIR}/html/unsupported/
-  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/ftv2node.png                     ${CMAKE_CURRENT_BINARY_DIR}/html/unsupported/
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${Eigen_BINARY_DIR}/doc/html/contrib
+  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Eigen_Silly_Professor_64x64.png  ${CMAKE_CURRENT_BINARY_DIR}/html/contrib/
+  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/ftv2pnode.png                    ${CMAKE_CURRENT_BINARY_DIR}/html/contrib/
+  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/ftv2node.png                     ${CMAKE_CURRENT_BINARY_DIR}/html/contrib/
   WORKING_DIRECTORY ${Eigen_BINARY_DIR}/doc
 )
 
 add_dependencies(doc-eigen-prerequisites all_snippets all_examples)
-add_dependencies(doc-unsupported-prerequisites unsupported_snippets unsupported_examples)
+add_dependencies(doc-contrib-prerequisites contrib_snippets contrib_examples)
 
 add_custom_target(doc ALL
   COMMAND doxygen
-  COMMAND doxygen Doxyfile-unsupported
+  COMMAND doxygen Doxyfile-contrib
   COMMAND ${CMAKE_COMMAND} -E copy ${Eigen_BINARY_DIR}/doc/html/group__TopicUnalignedArrayAssert.html ${Eigen_BINARY_DIR}/doc/html/TopicUnalignedArrayAssert.html
   COMMAND ${CMAKE_COMMAND} -E rename html eigen-doc
-  COMMAND ${CMAKE_COMMAND} -E remove eigen-doc/eigen-doc.tgz eigen-doc/unsupported/_formulas.log eigen-doc/_formulas.log
+  COMMAND ${CMAKE_COMMAND} -E remove eigen-doc/eigen-doc.tgz eigen-doc/contrib/_formulas.log eigen-doc/_formulas.log
   COMMAND ${CMAKE_COMMAND} -E tar cfz eigen-doc.tgz eigen-doc
   COMMAND ${CMAKE_COMMAND} -E rename eigen-doc.tgz eigen-doc/eigen-doc.tgz
   COMMAND ${CMAKE_COMMAND} -E rename eigen-doc html
   WORKING_DIRECTORY ${Eigen_BINARY_DIR}/doc)
 
-add_dependencies(doc doc-eigen-prerequisites doc-unsupported-prerequisites)
+add_dependencies(doc doc-eigen-prerequisites doc-contrib-prerequisites)
 
 # This target writes below CMAKE_INSTALL_PREFIX like any install rule, so it
 # follows EIGEN_INSTALL: with the option off, Eigen places no file there.
diff --git a/doc/CoeffwiseMathFunctionsTable.dox b/doc/CoeffwiseMathFunctionsTable.dox
index d33eb6e..cf1dcd9 100644
--- a/doc/CoeffwiseMathFunctionsTable.dox
+++ b/doc/CoeffwiseMathFunctionsTable.dox
@@ -568,7 +568,7 @@
 <tr>
 <th colspan="4">Error and gamma functions</th>
 </tr>
-<tr> <td colspan="4">  Require \c \#include \c <unsupported/Eigen/SpecialFunctions> </td></tr>
+<tr> <td colspan="4">  Require \c \#include \c <contrib/Eigen/SpecialFunctions> </td></tr>
 <tr>
   <td class="code">
   \anchor cwisetable_erf
@@ -647,7 +647,7 @@
 <tr>
 <th colspan="4">Special functions</th>
 </tr>
-<tr> <td colspan="4">  Require \c \#include \c <unsupported/Eigen/SpecialFunctions> </td></tr>
+<tr> <td colspan="4">  Require \c \#include \c <contrib/Eigen/SpecialFunctions> </td></tr>
 <tr>
   <td class="code">
   \anchor cwisetable_polygamma
diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index 2633c4f..b029124 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -17,7 +17,7 @@
                          "lu_module=This is defined in the %LU module. \code #include <Eigen/LU> \endcode" \
                          "qr_module=This is defined in the %QR module. \code #include <Eigen/QR> \endcode" \
                          "svd_module=This is defined in the %SVD module. \code #include <Eigen/SVD> \endcode" \
-                         "specialfunctions_module=This is defined in the \b unsupported SpecialFunctions module. \code #include <Eigen/SpecialFunctions> \endcode" \
+                         "specialfunctions_module=This is defined in the \b contrib SpecialFunctions module. \code #include <contrib/Eigen/SpecialFunctions> \endcode" \
                          label=\bug \
                          "matrixworld=<a href='#matrixonly' style='color:green;text-decoration: none;'>*</a>" \
                          "arrayworld=<a href='#arrayonly' style='color:blue;text-decoration: none;'>*</a>" \
@@ -63,8 +63,8 @@
                          ${Eigen_SOURCE_DIR}/doc/examples \
                          ${Eigen_SOURCE_DIR}/doc/special_examples \
                          ${Eigen_SOURCE_DIR}/doc/snippets \
-                         ${Eigen_SOURCE_DIR}/unsupported/doc/examples \
-                         ${Eigen_SOURCE_DIR}/unsupported/doc/snippets
+                         ${Eigen_SOURCE_DIR}/contrib/doc/examples \
+                         ${Eigen_SOURCE_DIR}/contrib/doc/snippets
 
 #                        ${Eigen_SOURCE_DIR}/Eigen/src/Core/products \
 #                        ${Eigen_SOURCE_DIR}/Eigen/src/Core/util/ForwardDeclarations.h \
@@ -94,10 +94,10 @@
                          ${Eigen_BINARY_DIR}/doc/examples \
                          ${Eigen_SOURCE_DIR}/doc/special_examples \
                          ${Eigen_BINARY_DIR}/doc/special_examples \
-                         ${Eigen_SOURCE_DIR}/unsupported/doc/snippets \
-                         ${Eigen_BINARY_DIR}/unsupported/doc/snippets \
-                         ${Eigen_SOURCE_DIR}/unsupported/doc/examples \
-                         ${Eigen_BINARY_DIR}/unsupported/doc/examples
+                         ${Eigen_SOURCE_DIR}/contrib/doc/snippets \
+                         ${Eigen_BINARY_DIR}/contrib/doc/snippets \
+                         ${Eigen_SOURCE_DIR}/contrib/doc/examples \
+                         ${Eigen_BINARY_DIR}/contrib/doc/examples
 IMAGE_PATH             = ${Eigen_BINARY_DIR}/doc/html
 # Prevent README.md from being considered a directory description (i.e. for Tensor).
 IMPLICIT_DIR_DOCS      = NO
diff --git a/doc/Overview.dox b/doc/Overview.dox
index 66c5f1f..17c4a66 100644
--- a/doc/Overview.dox
+++ b/doc/Overview.dox
@@ -23,7 +23,7 @@
 
 Finally, do not miss the search engine, useful to quickly get to the documentation of a given class or function.
 
-Want more? Checkout the <a href="unsupported/index.html">\em unsupported \em modules </a> documentation.
+Want more? Checkout the <a href="contrib/index.html">\em contrib \em modules </a> documentation.
 
 */
 
diff --git a/doc/SparseLinearSystems.dox b/doc/SparseLinearSystems.dox
index 03c89ea..9deb9a6 100644
--- a/doc/SparseLinearSystems.dox
+++ b/doc/SparseLinearSystems.dox
@@ -209,9 +209,9 @@
 \section BenchmarkRoutine
 Most of the time, all you need is to know how much time it will take to solve your system, and hopefully, what is the most suitable solver. You can benchmark solvers by timing them on matrices in <a href="http://math.nist.gov/MatrixMarket/formats.html">MatrixMarket Coordinate format</a>. See the `benchmarks/Sparse/` directory for example benchmarks.
 
-To export your matrices and right-hand-side vectors in the matrix-market format, you can use the unsupported SparseExtra module:
+To export your matrices and right-hand-side vectors in the matrix-market format, you can use the contrib SparseExtra module:
 \code
-#include <unsupported/Eigen/SparseExtra>
+#include <contrib/Eigen/SparseExtra>
 ...
 Eigen::saveMarket(A, "filename.mtx");
 Eigen::saveMarket(A, "filename_SPD.mtx", Eigen::Symmetric); // if A is symmetric-positive-definite
diff --git a/doc/TopicScalarTypes.dox b/doc/TopicScalarTypes.dox
index b116c16..d6e3d2e 100644
--- a/doc/TopicScalarTypes.dox
+++ b/doc/TopicScalarTypes.dox
@@ -61,7 +61,7 @@
 specializing NumTraits for it and providing the math functions that make sense for the type. The
 full recipe, with complete examples (an automatic-differentiation type and a GMP rational type),
 is given in \ref TopicCustomizing_CustomScalar. Ready-made support for the MPFR arbitrary-precision
-type is available in the unsupported module <a href="unsupported/group__MPRealSupport__Module.html">MPRealSupport</a>.
+type is available in the contrib module <a href="contrib/group__MPRealSupport__Module.html">MPRealSupport</a>.
 
 */
 
diff --git a/doc/examples/Cwise_erf.cpp b/doc/examples/Cwise_erf.cpp
index 8f9f4d6..17d1f2f 100644
--- a/doc/examples/Cwise_erf.cpp
+++ b/doc/examples/Cwise_erf.cpp
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <Eigen/Core>
-#include <unsupported/Eigen/SpecialFunctions>
+#include <contrib/Eigen/SpecialFunctions>
 #include <iostream>
 int main() {
   Eigen::Array4d v(-0.5, 2, 0, -7);
diff --git a/doc/examples/Cwise_erfc.cpp b/doc/examples/Cwise_erfc.cpp
index c2c5df1..b8b0e6d 100644
--- a/doc/examples/Cwise_erfc.cpp
+++ b/doc/examples/Cwise_erfc.cpp
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <Eigen/Core>
-#include <unsupported/Eigen/SpecialFunctions>
+#include <contrib/Eigen/SpecialFunctions>
 #include <iostream>
 int main() {
   Eigen::Array4d v(-0.5, 2, 0, -7);
diff --git a/doc/examples/Cwise_lgamma.cpp b/doc/examples/Cwise_lgamma.cpp
index fc45fbe..ce6188c 100644
--- a/doc/examples/Cwise_lgamma.cpp
+++ b/doc/examples/Cwise_lgamma.cpp
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <Eigen/Core>
-#include <unsupported/Eigen/SpecialFunctions>
+#include <contrib/Eigen/SpecialFunctions>
 #include <iostream>
 int main() {
   Eigen::Array4d v(0.5, 10, 0, -1);
diff --git a/failtest/bjorckpereyra_rectangular.cpp b/failtest/bjorckpereyra_rectangular.cpp
index f49ca3b..3f0387e 100644
--- a/failtest/bjorckpereyra_rectangular.cpp
+++ b/failtest/bjorckpereyra_rectangular.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include "../unsupported/Eigen/StructuredMatrices"
+#include "../contrib/Eigen/StructuredMatrices"
 
 #ifdef EIGEN_SHOULD_FAIL_TO_BUILD
 constexpr int Cols = 3;
diff --git a/failtest/erf_no_scalar_overload.cpp b/failtest/erf_no_scalar_overload.cpp
index 9255dc7..edb7ed4 100644
--- a/failtest/erf_no_scalar_overload.cpp
+++ b/failtest/erf_no_scalar_overload.cpp
@@ -1,4 +1,4 @@
-#include "../unsupported/Eigen/SpecialFunctions"
+#include "../contrib/Eigen/SpecialFunctions"
 
 // A custom scalar that does not provide erf. Eigen's approximations are tuned
 // for float and double and are not valid for it, so numext::erf must be
diff --git a/failtest/erfc_no_scalar_overload.cpp b/failtest/erfc_no_scalar_overload.cpp
index 57e9af2..30f0858 100644
--- a/failtest/erfc_no_scalar_overload.cpp
+++ b/failtest/erfc_no_scalar_overload.cpp
@@ -1,4 +1,4 @@
-#include "../unsupported/Eigen/SpecialFunctions"
+#include "../contrib/Eigen/SpecialFunctions"
 
 // A custom scalar that does not provide erfc. Eigen's approximations are tuned
 // for float and double and are not valid for it, so numext::erfc must be
diff --git a/failtest/vandermonde_int.cpp b/failtest/vandermonde_int.cpp
index 9f8b2af..99d2f51 100644
--- a/failtest/vandermonde_int.cpp
+++ b/failtest/vandermonde_int.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include "../unsupported/Eigen/StructuredMatrices"
+#include "../contrib/Eigen/StructuredMatrices"
 
 #ifdef EIGEN_SHOULD_FAIL_TO_BUILD
 using Scalar = int;
diff --git a/failtest/vandermonde_rectangular_square.cpp b/failtest/vandermonde_rectangular_square.cpp
index 6a682dc..d7217f8 100644
--- a/failtest/vandermonde_rectangular_square.cpp
+++ b/failtest/vandermonde_rectangular_square.cpp
@@ -1,7 +1,7 @@
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
 
-#include "../unsupported/Eigen/StructuredMatrices"
+#include "../contrib/Eigen/StructuredMatrices"
 
 #ifdef EIGEN_SHOULD_FAIL_TO_BUILD
 constexpr int Cols = 3;
diff --git a/scripts/add_spdx_headers.py b/scripts/add_spdx_headers.py
index 7460d8b..47b3d33 100755
--- a/scripts/add_spdx_headers.py
+++ b/scripts/add_spdx_headers.py
@@ -176,7 +176,7 @@
 
 
 def is_eigen_umbrella_header(rel: Path) -> bool:
-    """`Eigen/Core`, `unsupported/Eigen/Tensor`, etc. — extensionless C++ headers."""
+    """`Eigen/Core`, `contrib/Eigen/Tensor`, etc. — extensionless C++ headers."""
     parts = rel.parts
     if rel.suffix:
         return False
@@ -184,11 +184,11 @@
         return len(parts) == 2
     if (
         len(parts) >= 3
-        and parts[0] == "unsupported"
+        and parts[0] in ("contrib", "unsupported")
         and parts[1] == "Eigen"
         and parts[-1][:1].isupper()
     ):
-        # unsupported/Eigen/Tensor, ...
+        # contrib/Eigen/Tensor (real), unsupported/Eigen/Tensor (legacy shim), ...
         return True
     return False
 
diff --git a/scripts/affected_tests.py b/scripts/affected_tests.py
index b8f0e4d..65f8490 100644
--- a/scripts/affected_tests.py
+++ b/scripts/affected_tests.py
@@ -6,7 +6,7 @@
 
 Eigen is header-only, so a test is affected by a change exactly when its
 translation unit textually includes the changed file.  This script builds the
-include graph over ``Eigen/``, ``unsupported/Eigen/`` and the test trees, then
+include graph over ``Eigen/``, ``contrib/Eigen/``, ``unsupported/Eigen/`` and the test trees, then
 maps changed paths to the CMake test targets that reach them.
 
 The graph follows every ``#include`` regardless of preprocessor guards, so the
@@ -63,10 +63,12 @@
 import sys
 
 # Directories scanned to build the include graph.
-SCAN_ROOTS = ("Eigen", "unsupported/Eigen", "test", "unsupported/test", "failtest")
+# unsupported/Eigen holds only the legacy umbrella shims now, but they are
+# still headers a change can propagate through, so the graph keeps them.
+SCAN_ROOTS = ("Eigen", "contrib/Eigen", "unsupported/Eigen", "test", "contrib/test", "failtest")
 
 # Directories whose .cpp files are test translation units.
-TEST_ROOTS = ("test", "unsupported/test")
+TEST_ROOTS = ("test", "contrib/test")
 
 # Subtrees of TEST_ROOTS that are not part of this build.  test/buildsystem/
 # holds standalone CMake projects that test:linux:buildsystem configures on
@@ -115,8 +117,8 @@
     "debug/*",
     "demos/*",
     "doc/*",
-    "unsupported/benchmarks/*",
-    "unsupported/doc/*",
+    "contrib/benchmarks/*",
+    "contrib/doc/*",
 )
 
 # Changes matching these patterns invalidate the include-graph mapping itself
diff --git a/scripts/check_style.py b/scripts/check_style.py
index e354e97..cb0e4f3 100644
--- a/scripts/check_style.py
+++ b/scripts/check_style.py
@@ -44,21 +44,24 @@
                           hook_post_image_and_added, is_cxx_path, read_post_image)
 
 # Trees whose headers and tests must compile as C++14 (see AGENTS.md rule 3).
-CXX14_TREES = ("Eigen/", "unsupported/Eigen/", "test/", "unsupported/test/", "failtest/", "blas/", "lapack/")
+# unsupported/Eigen/ is kept for the legacy umbrella shims that still live there;
+# the implementation tree itself is contrib/.
+CXX14_TREES = ("Eigen/", "contrib/Eigen/", "unsupported/Eigen/", "test/", "contrib/test/", "failtest/", "blas/",
+               "lapack/")
 # Guarded exceptions with a documented newer requirement: SYCL sources build
 # only in the C++17 SYCL configurations, while duccfft and the structured-
 # binding failtests explicitly select C++17 in their test CMakeLists files.
 CXX17_PREFIXES = ("Eigen/src/Core/arch/SYCL/",)
 CXX17_FILES = {
     "test/sycl_basic.cpp",
-    "unsupported/Eigen/src/FFT/duccfft_impl.h",
-    "unsupported/test/duccfft.cpp",
+    "contrib/Eigen/src/FFT/duccfft_impl.h",
+    "contrib/test/duccfft.cpp",
     "failtest/structured_bindings_dynamic_matrix.cpp",
     "failtest/structured_bindings_dynamic_array.cpp",
     "failtest/structured_bindings_rowmajor.cpp",
 }
 # Library implementation headers, where numext:: is required over std:: math.
-LIBRARY_SRC_TREES = ("Eigen/src/", "unsupported/Eigen/src/")
+LIBRARY_SRC_TREES = ("Eigen/src/", "contrib/Eigen/src/")
 
 DOXYGEN = re.compile(r"^\s*(/\*\*|/\*!|///|//!)")
 LICENSE = re.compile(r"SPDX|Copyright|License|Mozilla Public", re.I)
@@ -303,8 +306,8 @@
     cxx17_path = (
         rel_path in CXX17_FILES
         or rel_path.startswith(CXX17_PREFIXES)
-        or (rel_path.startswith("unsupported/Eigen/src/Tensor/") and rel_path.endswith("Sycl.h"))
-        or (rel_path.startswith("unsupported/test/") and rel_path.endswith("_sycl.cpp"))
+        or (rel_path.startswith("contrib/Eigen/src/Tensor/") and rel_path.endswith("Sycl.h"))
+        or (rel_path.startswith("contrib/test/") and rel_path.endswith("_sycl.cpp"))
     )
     if rel_path.startswith(CXX14_TREES) and not cxx17_path:
         checks += CXX14_CHECKS
diff --git a/scripts/clang_tidy_hook.py b/scripts/clang_tidy_hook.py
index 46ee79d..5bc747e 100644
--- a/scripts/clang_tidy_hook.py
+++ b/scripts/clang_tidy_hook.py
@@ -24,7 +24,7 @@
 
 No compilation database is required: ``-std=c++14 -I<repo>`` parses any file
 in the C++14 trees, with ``test/`` added for the test sources and
-``unsupported/`` for the unsupported ones, which keeps the hook usable in a
+``contrib/`` for the contrib ones, which keeps the hook usable in a
 fresh checkout with no build directory.
 
 The hook fails open — a missing clang-tidy, an unparsable file, a translation
@@ -48,8 +48,12 @@
 
 # Parsing an umbrella costs about a second, so keep the hook off trees whose
 # conventions these checks do not describe (bench/, demos/, doc/ examples).
-CHECKED_TREES = ("Eigen/", "unsupported/Eigen/", "test/", "unsupported/test/", "failtest/", "blas/", "lapack/")
-SRC_TREES = ("Eigen/src/", "unsupported/Eigen/src/")
+# unsupported/Eigen/ is kept for the legacy umbrella shims that still live
+# there; the implementation tree itself is contrib/, which has no shims and
+# so needs the src-tree rules.
+CHECKED_TREES = ("Eigen/", "contrib/Eigen/", "unsupported/Eigen/", "test/", "contrib/test/", "failtest/", "blas/",
+                 "lapack/")
+SRC_TREES = ("Eigen/src/", "contrib/Eigen/src/")
 # Modules whose umbrella needs a third-party header we cannot assume is present.
 EXTERNAL_DEP_MODULES = ("AccelerateSupport", "CholmodSupport", "KLUSupport", "MetisSupport",
                         "PaStiXSupport", "PardisoSupport", "SPQRSupport", "SuperLUSupport",
@@ -60,7 +64,7 @@
 
 def module_of(rel_path):
     """Return the ``Eigen/src/<Module>`` name owning ``rel_path``, else None."""
-    m = re.match(r"^(?:unsupported/)?Eigen/src/([^/]+)/", rel_path)
+    m = re.match(r"^(?:contrib/)?Eigen/src/([^/]+)/", rel_path)
     return m.group(1) if m else None
 
 
@@ -83,7 +87,7 @@
             continue
         if hit and os.path.isfile(os.path.join(root, hit.group(1))):
             return hit.group(1)
-    fallback = ("unsupported/Eigen/" if rel_path.startswith("unsupported/") else "Eigen/") + module
+    fallback = ("contrib/Eigen/" if rel_path.startswith("contrib/") else "Eigen/") + module
     return fallback if os.path.isfile(os.path.join(root, fallback)) else None
 
 
@@ -110,16 +114,16 @@
 def compile_args(rel_path, root=REPO_ROOT):
     """Include paths sufficient to parse ``rel_path`` without a compile database.
 
-    Test sources reach ``main.h`` through ``test/``; the unsupported ones also
+    Test sources reach ``main.h`` through ``test/``; the contrib ones also
     include their module umbrellas as ``<Eigen/Tensor>``, which resolves only
-    with ``unsupported/`` on the path.  These are the directories
-    ``unsupported/test/CMakeLists.txt`` adds for them.
+    with ``contrib/`` on the path.  These are the directories
+    ``contrib/test/CMakeLists.txt`` adds for them.
     """
     args = ["-std=c++14", "-I" + root]
-    if rel_path.startswith(("test/", "unsupported/test/")):
+    if rel_path.startswith(("test/", "contrib/test/")):
         args += ["-I" + os.path.join(root, "test")]
-    if rel_path.startswith("unsupported/test/"):
-        args += ["-I" + os.path.join(root, "unsupported")]
+    if rel_path.startswith("contrib/test/"):
+        args += ["-I" + os.path.join(root, "contrib")]
     cuda = cuda_include_dir()
     if cuda:
         args += ["-isystem", cuda]
diff --git a/scripts/format.sh b/scripts/format.sh
index de34109..dc6d619 100755
--- a/scripts/format.sh
+++ b/scripts/format.sh
@@ -7,6 +7,7 @@
 
 # Format main headers without extensions
 find Eigen -maxdepth 1 -type f | xargs -n 1 -P 0 clang-format-17 -i
+find contrib/Eigen -maxdepth 2 -type f -not -name '*.txt' | xargs -n 1 -P 0 clang-format-17 -i
 find unsupported/Eigen -maxdepth 2 -type f -not -name '*.txt' | xargs -n 1 -P 0 clang-format-17 -i
 
 # Format examples
diff --git a/scripts/style_common.py b/scripts/style_common.py
index f86d8c5..8d3bd69 100644
--- a/scripts/style_common.py
+++ b/scripts/style_common.py
@@ -26,7 +26,9 @@
 
 REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 CXX_EXT = {".h", ".hpp", ".hxx", ".cpp", ".cc", ".cxx", ".cu", ".cuh", ".inc"}
-EXTENSIONLESS_HEADER_TREES = ("Eigen/", "unsupported/Eigen/")
+# unsupported/Eigen/ still holds the legacy umbrella shims, which are
+# extensionless headers too.
+EXTENSIONLESS_HEADER_TREES = ("Eigen/", "contrib/Eigen/", "unsupported/Eigen/")
 
 
 def is_cxx_path(rel_path):
diff --git a/scripts/test_affected_tests.py b/scripts/test_affected_tests.py
index f4c2dcb..2c7af0a 100644
--- a/scripts/test_affected_tests.py
+++ b/scripts/test_affected_tests.py
@@ -62,8 +62,8 @@
         "add_executable(installed_consumer ../main.cpp)\n",
     "test/buildsystem/consumers/subproject/CMakeLists.txt":
         "add_executable(subproject_consumer ../main.cpp)\n",
-    "unsupported/test/extra.cpp": '#include "../../test/main.h"\n',
-    "unsupported/test/CMakeLists.txt": "ei_add_test(extra)\n",
+    "contrib/test/extra.cpp": '#include "../../test/main.h"\n',
+    "contrib/test/CMakeLists.txt": "ei_add_test(extra)\n",
     "failtest/svd_int.cpp": "#include <Eigen/SVD>\n",
     "failtest/const_block.cpp": "#include <Eigen/Core>\n",
     "failtest/CMakeLists.txt": 'ei_add_failtest("svd_int")\nei_add_failtest("const_block")\n',
@@ -95,9 +95,9 @@
 def test_fixture_graph(root):
     graph = IncludeGraph(root)
     sources = sorted(test_registrations(graph).targets)
-    check(sources == ["test/after_gpu.cpp", "test/bdcsvd.cpp", "test/block.cpp",
-                      "test/dense.cpp", "test/gpu_basic.cu", "test/multitu.cpp",
-                      "test/multitu_main.cpp", "unsupported/test/extra.cpp"],
+    check(sources == ["contrib/test/extra.cpp", "test/after_gpu.cpp", "test/bdcsvd.cpp",
+                      "test/block.cpp", "test/dense.cpp", "test/gpu_basic.cu",
+                      "test/multitu.cpp", "test/multitu_main.cpp"],
           "test sources discovered in both trees, got %s" % sources)
 
     # A leaf header reaches only the tests whose closure includes it.
@@ -138,7 +138,7 @@
     # own CMakeLists.txt -- which must not trip the full-rebuild rule.
     sel = select(graph, ["doc/TopicLazyEvaluation.dox", "README.md", ".agents/ci.md",
                          "benchmarks/Core/bench_reductions.cpp",
-                         "unsupported/benchmarks/GPU/CMakeLists.txt",
+                         "contrib/benchmarks/GPU/CMakeLists.txt",
                          "doc/CMakeLists.txt", "debug/gdb/printers.py"])
     check(sel.mode == "none", "docs and benchmarks select nothing, got %s (%s)"
           % (sel.mode, sel.reasons))
@@ -195,7 +195,7 @@
 
     # Mixed changes union their selections.
     graph = IncludeGraph(root)
-    sel = select(graph, ["Eigen/src/SVD/BDCSVD.h", "unsupported/test/extra.cpp"])
+    sel = select(graph, ["Eigen/src/SVD/BDCSVD.h", "contrib/test/extra.cpp"])
     check(sel.mode == "targets" and targets_of(sel) == ["bdcsvd", "dense", "extra"],
           "mixed changes union, got %s" % targets_of(sel))
 
@@ -318,13 +318,13 @@
 
 FOREACH_FIXTURE = {
     "test/main.h": "",
-    "unsupported/test/GPU/gpu_test_helpers.h": '#include "../../../test/main.h"\n',
-    "unsupported/test/GPU/device_matrix.cpp": '#include "gpu_test_helpers.h"\n',
-    "unsupported/test/GPU/cusolver_llt.cpp": '#include "gpu_test_helpers.h"\n',
-    "unsupported/test/GPU/cusolver_qr.cpp": '#include "gpu_test_helpers.h"\n',
-    "unsupported/test/GPU/from_variable.cpp": '#include "gpu_test_helpers.h"\n',
-    "unsupported/test/GPU/unregistered.cpp": '#include "gpu_test_helpers.h"\n',
-    "unsupported/test/GPU/CMakeLists.txt": """function(ei_add_gpu_test test_name)
+    "contrib/test/GPU/gpu_test_helpers.h": '#include "../../../test/main.h"\n',
+    "contrib/test/GPU/device_matrix.cpp": '#include "gpu_test_helpers.h"\n',
+    "contrib/test/GPU/cusolver_llt.cpp": '#include "gpu_test_helpers.h"\n',
+    "contrib/test/GPU/cusolver_qr.cpp": '#include "gpu_test_helpers.h"\n',
+    "contrib/test/GPU/from_variable.cpp": '#include "gpu_test_helpers.h"\n',
+    "contrib/test/GPU/unregistered.cpp": '#include "gpu_test_helpers.h"\n',
+    "contrib/test/GPU/CMakeLists.txt": """function(ei_add_gpu_test test_name)
   ei_add_test(${test_name} "" "CUDA::cudart_static")
   foreach(t ${_targets})
     add_dependencies(buildtests_gpu ${t})
@@ -356,32 +356,32 @@
         graph = IncludeGraph(root)
         sources = test_registrations(graph).targets
 
-        check(sources.get("unsupported/test/GPU/device_matrix.cpp") == "device_matrix",
+        check(sources.get("contrib/test/GPU/device_matrix.cpp") == "device_matrix",
               "a literal ei_add_gpu_test registers its source, got %s"
-              % sources.get("unsupported/test/GPU/device_matrix.cpp"))
-        check(sources.get("unsupported/test/GPU/cusolver_llt.cpp") == "cusolver_llt"
-              and sources.get("unsupported/test/GPU/cusolver_qr.cpp") == "cusolver_qr",
+              % sources.get("contrib/test/GPU/device_matrix.cpp"))
+        check(sources.get("contrib/test/GPU/cusolver_llt.cpp") == "cusolver_llt"
+              and sources.get("contrib/test/GPU/cusolver_qr.cpp") == "cusolver_qr",
               "foreach(... IN ITEMS ...) expands to one registration per item, got %s"
               % sorted(sources))
 
         # ei_add_test(${test_name}) inside the wrapper's own body is a function
         # parameter, not a loop item, so it must not register anything.
-        check("unsupported/test/GPU/test_name.cpp" not in sources
+        check("contrib/test/GPU/test_name.cpp" not in sources
               and "test_name" not in set(sources.values()),
               "the wrapper's own parameter is not a registration, got %s" % sorted(sources))
 
         # A .cpp whose only registration iterates a variable, and one with no
         # registration at all, must both reach the error path rather than being
         # assumed registered because of where they live.
-        for path in ("unsupported/test/GPU/from_variable.cpp",
-                     "unsupported/test/GPU/unregistered.cpp"):
+        for path in ("contrib/test/GPU/from_variable.cpp",
+                     "contrib/test/GPU/unregistered.cpp"):
             check(path not in sources, "%s is not registered, got %s" % (path, sources.get(path)))
             sel = select(graph, [path])
             check(sel.mode == "error",
                   "%s fails selection, got %s (%s)" % (path, sel.mode, sel.reasons))
 
         # The header the registered tests share still reaches them.
-        sel = select(graph, ["unsupported/test/GPU/gpu_test_helpers.h"], max_fraction=1.0)
+        sel = select(graph, ["contrib/test/GPU/gpu_test_helpers.h"], max_fraction=1.0)
         check(sel.mode == "targets"
               and targets_of(sel) == ["cusolver_llt", "cusolver_qr", "device_matrix"],
               "the GPU header reaches its registered tests, got %s (%s)"
@@ -492,22 +492,22 @@
 
     # Every GPU module test is registered by a call the parser can see, so a
     # source added without a registration reaches the error path.
-    gpu_dir = os.path.join(root, "unsupported", "test", "GPU")
+    gpu_dir = os.path.join(root, "contrib", "test", "GPU")
     if os.path.isdir(gpu_dir):
-        gpu_sources = sorted("unsupported/test/GPU/" + name for name in os.listdir(gpu_dir)
+        gpu_sources = sorted("contrib/test/GPU/" + name for name in os.listdir(gpu_dir)
                              if name.endswith(".cpp"))
         unmapped = [rel for rel in gpu_sources if rel not in source_targets]
         check(gpu_sources and not unmapped,
               "every GPU test source is registered, got %s unmapped of %d"
               % (unmapped, len(gpu_sources)))
-        check(source_targets.get("unsupported/test/GPU/cusolver_svd.cpp") == "cusolver_svd",
+        check(source_targets.get("contrib/test/GPU/cusolver_svd.cpp") == "cusolver_svd",
               "a foreach-registered GPU test maps to its target, got %s"
-              % source_targets.get("unsupported/test/GPU/cusolver_svd.cpp"))
+              % source_targets.get("contrib/test/GPU/cusolver_svd.cpp"))
         probe = os.path.join(gpu_dir, "affected_tests_probe.cpp")
         with open(probe, "w") as handle:
             handle.write('#include "gpu_test_helpers.h"\n')
         try:
-            sel = select(IncludeGraph(root), ["unsupported/test/GPU/affected_tests_probe.cpp"])
+            sel = select(IncludeGraph(root), ["contrib/test/GPU/affected_tests_probe.cpp"])
             check(sel.mode == "error",
                   "an unregistered GPU source fails selection, got %s" % sel.mode)
         finally:
diff --git a/scripts/test_check_style.py b/scripts/test_check_style.py
index cd8cdb2..b51fff1 100644
--- a/scripts/test_check_style.py
+++ b/scripts/test_check_style.py
@@ -79,16 +79,16 @@
     # Sources with a documented C++17 requirement are exempt from the C++14 checks...
     assert_clean("test/sycl_basic.cpp", "if constexpr (kSize > 4) {}\n")
     assert_clean("Eigen/src/Core/arch/SYCL/PacketMath.h", "if constexpr (kSize > 4) {}\n")
-    assert_clean("unsupported/Eigen/src/Tensor/TensorDeviceSycl.h", "if constexpr (kSize > 4) {}\n")
-    assert_clean("unsupported/test/tensor_sycl.cpp", "if constexpr (kSize > 4) {}\n")
-    assert_clean("unsupported/Eigen/src/FFT/duccfft_impl.h", "if constexpr (kSize > 4) {}\n")
-    assert_clean("unsupported/test/duccfft.cpp", "if constexpr (kSize > 4) {}\n")
+    assert_clean("contrib/Eigen/src/Tensor/TensorDeviceSycl.h", "if constexpr (kSize > 4) {}\n")
+    assert_clean("contrib/test/tensor_sycl.cpp", "if constexpr (kSize > 4) {}\n")
+    assert_clean("contrib/Eigen/src/FFT/duccfft_impl.h", "if constexpr (kSize > 4) {}\n")
+    assert_clean("contrib/test/duccfft.cpp", "if constexpr (kSize > 4) {}\n")
     assert_clean("failtest/structured_bindings_dynamic_matrix.cpp", "if constexpr (kSize > 4) {}\n")
     assert_clean("failtest/structured_bindings_dynamic_array.cpp", "if constexpr (kSize > 4) {}\n")
     assert_clean("failtest/structured_bindings_rowmajor.cpp", "if constexpr (kSize > 4) {}\n")
     # A coincidental substring is not a documented C++17 requirement.
     assert_flags("test/not_sycl_related.cpp", "if constexpr (kSize > 4) {}\n", "EIGEN_IF_CONSTEXPR")
-    assert_flags("unsupported/Eigen/src/FFT/kissfft_impl.h", "if constexpr (kSize > 4) {}\n", "EIGEN_IF_CONSTEXPR")
+    assert_flags("contrib/Eigen/src/FFT/kissfft_impl.h", "if constexpr (kSize > 4) {}\n", "EIGEN_IF_CONSTEXPR")
     # ...but not from the other conventions.
     assert_flags("test/sycl_basic.cpp", "std::integral_constant<bool, true> b;\n", "bool_constant")
 
diff --git a/scripts/test_clang_tidy_hook.py b/scripts/test_clang_tidy_hook.py
index 1bb8b7f..65857b4 100644
--- a/scripts/test_clang_tidy_hook.py
+++ b/scripts/test_clang_tidy_hook.py
@@ -49,7 +49,7 @@
 def test_module_of():
     assert module_of("Eigen/src/Core/Block.h") == "Core"
     assert module_of("Eigen/src/Core/arch/AVX/PacketMath.h") == "Core"
-    assert module_of("unsupported/Eigen/src/Tensor/TensorBlock.h") == "Tensor"
+    assert module_of("contrib/Eigen/src/Tensor/TensorBlock.h") == "Tensor"
     assert module_of("test/block.cpp") is None
     assert module_of("Eigen/Core") is None
 
@@ -58,7 +58,7 @@
     # Read from the module's InternalHeaderCheck.h `#error` directive.
     assert umbrella_for("Eigen/src/Core/Block.h") == "Eigen/Core"
     # The Tensor module's umbrella lives outside its own directory tree.
-    assert umbrella_for("unsupported/Eigen/src/Tensor/TensorBlock.h") == "unsupported/Eigen/Tensor"
+    assert umbrella_for("contrib/Eigen/src/Tensor/TensorBlock.h") == "contrib/Eigen/Tensor"
     # Arch backends nested below the module root carry no directive of their
     # own and fall back to <root>/<Module>.
     assert umbrella_for("Eigen/src/Core/arch/AVX/PacketMath.h") == "Eigen/Core"
@@ -66,7 +66,7 @@
     assert umbrella_for("Eigen/src/CholmodSupport/CholmodSupport.h") is None
     # Every module in the tree must resolve, or the hook silently skips files.
     unresolved = []
-    for tree in ("Eigen/src", "unsupported/Eigen/src"):
+    for tree in ("Eigen/src", "contrib/Eigen/src"):
         for module in sorted(os.listdir(os.path.join(REPO_ROOT, tree))):
             rel = "%s/%s/InternalHeaderCheck.h" % (tree, module)
             if not os.path.isfile(os.path.join(REPO_ROOT, rel)):
@@ -103,13 +103,13 @@
     assert "-std=c++14" in args and "-I" + REPO_ROOT in args
     # Test sources include main.h from test/.
     assert any(a.endswith("/test") for a in compile_args("test/block.cpp"))
-    assert any(a.endswith("/test") for a in compile_args("unsupported/test/tensor_block_access.cpp"))
+    assert any(a.endswith("/test") for a in compile_args("contrib/test/tensor_block_access.cpp"))
     assert not any(a.endswith("/test") for a in compile_args("Eigen/src/Core/Block.h"))
-    # Unsupported test sources include their umbrellas as <Eigen/Tensor>, which
-    # only resolves with unsupported/ on the path; nothing else needs it.
-    assert any(a.endswith("/unsupported") for a in compile_args("unsupported/test/tensor_block_access.cpp"))
-    assert not any(a.endswith("/unsupported") for a in compile_args("test/block.cpp"))
-    assert not any(a.endswith("/unsupported") for a in compile_args("unsupported/Eigen/src/Tensor/TensorBlock.h"))
+    # Contrib test sources include their umbrellas as <Eigen/Tensor>, which
+    # only resolves with contrib/ on the path; nothing else needs it.
+    assert any(a.endswith("/contrib") for a in compile_args("contrib/test/tensor_block_access.cpp"))
+    assert not any(a.endswith("/contrib") for a in compile_args("test/block.cpp"))
+    assert not any(a.endswith("/contrib") for a in compile_args("contrib/Eigen/src/Tensor/TensorBlock.h"))
 
 
 def test_cuda_include_dir():
@@ -125,7 +125,7 @@
             with open(os.path.join(include, "cuda_runtime.h"), "w", encoding="utf-8") as handle:
                 handle.write("\n")
             assert cuda_include_dir(absent) == include
-            assert compile_args("unsupported/Eigen/src/GPU/DeviceMatrix.h")[-2:] == ["-isystem", include]
+            assert compile_args("contrib/Eigen/src/GPU/DeviceMatrix.h")[-2:] == ["-isystem", include]
     finally:
         for name, value in saved.items():
             if value is None:
@@ -228,25 +228,25 @@
         assert len(diagnostics) == 1 and "modernize-use-using" in diagnostics[0], diagnostics
 
 
-def test_unsupported_test_source_is_checked():
-    """An unsupported test source includes its module umbrella as <Eigen/X>,
-    which resolves only through unsupported/; without that path every such
+def test_contrib_test_source_is_checked():
+    """A contrib test source includes its module umbrella as <Eigen/X>,
+    which resolves only through contrib/; without that path every such
     file was skipped as a translation unit that did not compile."""
     if shutil.which("clang-tidy") is None:
-        print("SKIP test_unsupported_test_source_is_checked (clang-tidy not installed)")
+        print("SKIP test_contrib_test_source_is_checked (clang-tidy not installed)")
         return
-    with tempfile.TemporaryDirectory(prefix="tidy_unsupported_test_") as tmp:
-        os.makedirs(os.path.join(tmp, "unsupported", "Eigen"))
-        os.makedirs(os.path.join(tmp, "unsupported", "test"))
+    with tempfile.TemporaryDirectory(prefix="tidy_contrib_test_") as tmp:
+        os.makedirs(os.path.join(tmp, "contrib", "Eigen"))
+        os.makedirs(os.path.join(tmp, "contrib", "test"))
         with open(os.path.join(tmp, ".clang-tidy"), "w") as handle:
             handle.write("Checks: '-*,modernize-use-using'\n")
-        with open(os.path.join(tmp, "unsupported", "Eigen", "Probe"), "w") as handle:
+        with open(os.path.join(tmp, "contrib", "Eigen", "Probe"), "w") as handle:
             handle.write("#define EIGEN_PROBE_MODULE_H\n")
-        with open(os.path.join(tmp, "unsupported", "test", "probe.cpp"), "w") as handle:
+        with open(os.path.join(tmp, "contrib", "test", "probe.cpp"), "w") as handle:
             handle.write("#include <Eigen/Probe>\n"
                          "typedef int AddedAlias;\n")
 
-        diagnostics, skipped = run_clang_tidy({"unsupported/test/probe.cpp": {2}}, root=tmp)
+        diagnostics, skipped = run_clang_tidy({"contrib/test/probe.cpp": {2}}, root=tmp)
         assert not skipped, skipped
         assert len(diagnostics) == 1 and "modernize-use-using" in diagnostics[0], diagnostics
 
diff --git a/test/buildsystem/run_scenario.cmake b/test/buildsystem/run_scenario.cmake
index 9ad01d1..feb98c1 100644
--- a/test/buildsystem/run_scenario.cmake
+++ b/test/buildsystem/run_scenario.cmake
@@ -188,11 +188,12 @@
 endfunction()
 
 # Asserts the install tree holds nothing Eigen contributes: headers from the
-# supported and unsupported trees, the signature file, eigen3.pc, and the
-# CMake package files.
+# supported and contributed trees, the legacy unsupported/ shims, the signature
+# file, eigen3.pc, and the CMake package files.
 function(bs_assert_no_eigen_installed)
   bs_assert_not_installed("/Eigen/Core$" "supported Eigen header")
-  bs_assert_not_installed("/unsupported/Eigen/Tensor$" "unsupported Eigen header")
+  bs_assert_not_installed("/contrib/Eigen/Tensor$" "contributed Eigen header")
+  bs_assert_not_installed("/unsupported/Eigen/Tensor$" "legacy unsupported Eigen shim")
   bs_assert_not_installed("signature_of_eigen3_matrix_library$" "Eigen signature file")
   bs_assert_not_installed("eigen3\\.pc$" "eigen3.pc")
   bs_assert_not_installed("Eigen3Config\\.cmake$" "Eigen3 CMake package")
@@ -203,7 +204,8 @@
 function(bs_assert_eigen_headers_installed)
   bs_assert_installed("/Eigen/Core$" "supported Eigen header")
   bs_assert_installed("/Eigen/Dense$" "Eigen/Dense umbrella")
-  bs_assert_installed("/unsupported/Eigen/Tensor$" "unsupported Eigen header")
+  bs_assert_installed("/contrib/Eigen/Tensor$" "contributed Eigen header")
+  bs_assert_installed("/unsupported/Eigen/Tensor$" "legacy unsupported Eigen shim")
   bs_assert_installed("signature_of_eigen3_matrix_library$" "Eigen signature file")
 endfunction()
 
diff --git a/test/eigensolver_selfadjoint.cpp b/test/eigensolver_selfadjoint.cpp
index 5f7a32a..fdb3557 100644
--- a/test/eigensolver_selfadjoint.cpp
+++ b/test/eigensolver_selfadjoint.cpp
@@ -19,7 +19,7 @@
 #include <limits>
 #include <Eigen/Eigenvalues>
 #include <Eigen/SparseCore>
-#include <unsupported/Eigen/MatrixFunctions>
+#include <contrib/Eigen/MatrixFunctions>
 
 template <typename Scalar>
 struct selfadjoint_eigensolver_test_rescale {
diff --git a/test/metis_support.cpp b/test/metis_support.cpp
index 063131b..e782db0 100644
--- a/test/metis_support.cpp
+++ b/test/metis_support.cpp
@@ -11,7 +11,7 @@
 #include "sparse_solver.h"
 #include <Eigen/SparseLU>
 #include <Eigen/MetisSupport>
-#include <unsupported/Eigen/SparseExtra>
+#include <contrib/Eigen/SparseExtra>
 
 template <typename T>
 void test_metis_T() {
diff --git a/test/pastix_support.cpp b/test/pastix_support.cpp
index 1cb58f7..ff665f8 100644
--- a/test/pastix_support.cpp
+++ b/test/pastix_support.cpp
@@ -12,7 +12,7 @@
 #define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
 #include "sparse_solver.h"
 #include <Eigen/PaStiXSupport>
-#include <unsupported/Eigen/SparseExtra>
+#include <contrib/Eigen/SparseExtra>
 
 template <typename T>
 void test_pastix_T() {
diff --git a/test/product_large.cpp b/test/product_large.cpp
index 0e17db6..6d4eb84 100644
--- a/test/product_large.cpp
+++ b/test/product_large.cpp
@@ -83,7 +83,7 @@
 
     // An explicit override has to govern blocking on its own. The detected per-CPU L3 share also
     // feeds the rhs-panel budget, so leaving it set would silently overrule callers that force
-    // small cache sizes to exercise multi-pass blocking (unsupported/test/tensor_contraction.cpp
+    // small cache sizes to exercise multi-pass blocking (contrib/test/tensor_contraction.cpp
     // does exactly that).
     setCpuCacheSizes(896, 1920, 2944);
     std::ptrdiff_t forced_l1, forced_l2, forced_l3, forced_l3_per_cpu = -1;
diff --git a/test/ulp_accuracy/ulp_accuracy.cpp b/test/ulp_accuracy/ulp_accuracy.cpp
index be6cba9..eef7c8b 100644
--- a/test/ulp_accuracy/ulp_accuracy.cpp
+++ b/test/ulp_accuracy/ulp_accuracy.cpp
@@ -16,7 +16,7 @@
 // SPDX-License-Identifier: MPL-2.0
 
 #include <Eigen/Core>
-#include <unsupported/Eigen/SpecialFunctions>
+#include <contrib/Eigen/SpecialFunctions>
 
 #ifdef EIGEN_HAS_MPFR
 #include <mpfr.h>
diff --git a/unsupported/CMakeLists.txt b/unsupported/CMakeLists.txt
index 48c5033..5312d54 100644
--- a/unsupported/CMakeLists.txt
+++ b/unsupported/CMakeLists.txt
@@ -1,14 +1,9 @@
 # SPDX-FileCopyrightText: The Eigen Authors
 # SPDX-License-Identifier: MPL-2.0
 
+# Backward-compatibility shell for the legacy unsupported/ tree. The real
+# content moved to ../contrib/ in Eigen 5.x; only forwarding headers remain
+# here so that existing user code with #include <unsupported/Eigen/...> keeps
+# building. Tests, docs, and benchmarks live under ../contrib/.
+
 add_subdirectory(Eigen)
-if(EIGEN_BUILD_DOC)
-  add_subdirectory(doc EXCLUDE_FROM_ALL)
-endif()
-if(EIGEN_BUILD_TESTING)
-  if(EIGEN_LEAVE_TEST_IN_ALL_TARGET)
-    add_subdirectory(test) # CTest automatic test building relies on the "all" target.
-  else()
-    add_subdirectory(test EXCLUDE_FROM_ALL)
-  endif()
-endif()
diff --git a/unsupported/Eigen/AdolcForward b/unsupported/Eigen/AdolcForward
index 49403d0..2050bb0 100644
--- a/unsupported/Eigen/AdolcForward
+++ b/unsupported/Eigen/AdolcForward
@@ -1,158 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
-//
-// 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
-
-#ifndef EIGEN_ADOLC_FORWARD_MODULE_H
-#define EIGEN_ADOLC_FORWARD_MODULE_H
-
-//--------------------------------------------------------------------------------
 //
-// This file provides support for adolc's adouble type in forward mode.
-// ADOL-C is a C++ automatic differentiation library,
-// see https://projects.coin-or.org/ADOL-C for more information.
-//
-// Note that the maximal number of directions is controlled by
-// the preprocessor token NUMBER_DIRECTIONS. The default is 2.
-//
-//--------------------------------------------------------------------------------
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/AdolcForward>
+// directly. This shim preserves the legacy include path.
 
-#define ADOLC_TAPELESS
-#ifndef NUMBER_DIRECTIONS
-#define NUMBER_DIRECTIONS 2
-#endif
-#include <adolc/adtl.h>
+#ifndef EIGEN_UNSUPPORTED_ADOLCFORWARD_FORWARD_H
+#define EIGEN_UNSUPPORTED_ADOLCFORWARD_FORWARD_H
 
-// adolc defines some very stupid macros:
-#if defined(malloc)
-#undef malloc
-#endif
+#include "../../contrib/Eigen/AdolcForward"  // IWYU pragma: export
 
-#if defined(calloc)
-#undef calloc
-#endif
-
-#if defined(realloc)
-#undef realloc
-#endif
-
-#include "../../Eigen/Core"
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/**
- * \defgroup AdolcForward_Module Adolc forward module
- * This module provides support for adolc's adouble type in forward mode.
- * ADOL-C is a C++ automatic differentiation library,
- * see https://projects.coin-or.org/ADOL-C for more information.
- * It mainly consists in:
- *  - a struct Eigen::NumTraits<adtl::adouble> specialization
- *  - overloads of internal::* math function for adtl::adouble type.
- *
- * Note that the maximal number of directions is controlled by
- * the preprocessor token NUMBER_DIRECTIONS. The default is 2.
- *
- * \code
- * #include <unsupported/Eigen/AdolcForward>
- * \endcode
- */
-//@{
-
-}  // namespace Eigen
-
-// Eigen's require a few additional functions which must be defined in the same namespace
-// than the custom scalar type own namespace
-namespace adtl {
-
-inline const adouble& conj(const adouble& x) { return x; }
-inline const adouble& real(const adouble& x) { return x; }
-inline adouble imag(const adouble&) { return 0.; }
-inline adouble abs(const adouble& x) { return fabs(x); }
-inline adouble abs2(const adouble& x) { return x * x; }
-
-inline bool(isinf)(const adouble& x) { return (Eigen::numext::isinf)(x.getValue()); }
-inline bool(isnan)(const adouble& x) { return (Eigen::numext::isnan)(x.getValue()); }
-
-}  // namespace adtl
-
-namespace Eigen {
-
-template <>
-struct NumTraits<adtl::adouble> : NumTraits<double> {
-  typedef adtl::adouble Real;
-  typedef adtl::adouble NonInteger;
-  typedef adtl::adouble Nested;
-  enum {
-    IsComplex = 0,
-    IsInteger = 0,
-    IsSigned = 1,
-    RequireInitialization = 1,
-    ReadCost = 1,
-    AddCost = 1,
-    MulCost = 1
-  };
-};
-
-template <typename Functor>
-class AdolcForwardJacobian : public Functor {
-  typedef adtl::adouble ActiveScalar;
-
- public:
-  AdolcForwardJacobian() : Functor() {}
-  AdolcForwardJacobian(const Functor& f) : Functor(f) {}
-
-  // forward constructors
-  template <typename T0>
-  AdolcForwardJacobian(const T0& a0) : Functor(a0) {}
-  template <typename T0, typename T1>
-  AdolcForwardJacobian(const T0& a0, const T1& a1) : Functor(a0, a1) {}
-  template <typename T0, typename T1, typename T2>
-  AdolcForwardJacobian(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2) {}
-
-  typedef typename Functor::InputType InputType;
-  typedef typename Functor::ValueType ValueType;
-  typedef typename Functor::JacobianType JacobianType;
-
-  typedef Matrix<ActiveScalar, InputType::SizeAtCompileTime, 1> ActiveInput;
-  typedef Matrix<ActiveScalar, ValueType::SizeAtCompileTime, 1> ActiveValue;
-
-  void operator()(const InputType& x, ValueType* v, JacobianType* _jac) const {
-    eigen_assert(v != 0);
-    if (!_jac) {
-      Functor::operator()(x, v);
-      return;
-    }
-
-    JacobianType& jac = *_jac;
-
-    ActiveInput ax = x.template cast<ActiveScalar>();
-    ActiveValue av(jac.rows());
-
-    for (int j = 0; j < jac.cols(); j++)
-      for (int i = 0; i < jac.cols(); i++) ax[i].setADValue(j, i == j ? 1 : 0);
-
-    Functor::operator()(ax, &av);
-
-    for (int i = 0; i < jac.rows(); i++) {
-      (*v)[i] = av[i].getValue();
-      for (int j = 0; j < jac.cols(); j++) jac.coeffRef(i, j) = av[i].getADValue(j);
-    }
-  }
-
- protected:
-};
-
-//@}
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_ADOLC_FORWARD_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_ADOLCFORWARD_FORWARD_H
diff --git a/unsupported/Eigen/AlignedVector3 b/unsupported/Eigen/AlignedVector3
index e2cea0a..1e63deb 100644
--- a/unsupported/Eigen/AlignedVector3
+++ b/unsupported/Eigen/AlignedVector3
@@ -1,212 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/AlignedVector3>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_ALIGNED_VECTOR3_MODULE_H
-#define EIGEN_ALIGNED_VECTOR3_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_ALIGNEDVECTOR3_FORWARD_H
+#define EIGEN_UNSUPPORTED_ALIGNEDVECTOR3_FORWARD_H
 
-#include "../../Eigen/Geometry"
+#include "../../contrib/Eigen/AlignedVector3"  // IWYU pragma: export
 
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/**
- * \defgroup AlignedVector3_Module Aligned vector3 module
- *
- * \code
- * #include <unsupported/Eigen/AlignedVector3>
- * \endcode
- */
-//@{
-
-/** \class AlignedVector3
- *
- * \brief A vectorization friendly 3D vector
- *
- * This class represents a 3D vector internally using a 4D vector
- * such that vectorization can be seamlessly enabled. Of course,
- * the same result can be achieved by directly using a 4D vector.
- * This class makes this process simpler.
- *
- */
-// TODO: Specialize Cwise.
-template <typename Scalar_>
-class AlignedVector3;
-
-namespace internal {
-template <typename Scalar_>
-struct traits<AlignedVector3<Scalar_> > : traits<Matrix<Scalar_, 3, 1, 0, 4, 1> > {};
-}  // namespace internal
-
-template <typename Scalar_>
-class AlignedVector3 : public MatrixBase<AlignedVector3<Scalar_> > {
-  typedef Matrix<Scalar_, 4, 1> CoeffType;
-  CoeffType m_coeffs;
-
- public:
-  typedef MatrixBase<AlignedVector3<Scalar_> > Base;
-  EIGEN_DENSE_PUBLIC_INTERFACE(AlignedVector3)
-  using Base::operator*;
-
-  inline Index rows() const { return 3; }
-  inline Index cols() const { return 1; }
-
-  Scalar* data() { return m_coeffs.data(); }
-  const Scalar* data() const { return m_coeffs.data(); }
-  Index innerStride() const { return 1; }
-  Index outerStride() const { return 3; }
-
-  inline const Scalar& coeff(Index row, Index col) const { return m_coeffs.coeff(row, col); }
-
-  inline Scalar& coeffRef(Index row, Index col) { return m_coeffs.coeffRef(row, col); }
-
-  inline const Scalar& coeff(Index index) const { return m_coeffs.coeff(index); }
-
-  inline Scalar& coeffRef(Index index) { return m_coeffs.coeffRef(index); }
-
-  inline AlignedVector3() {}
-
-  inline AlignedVector3(const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, Scalar(0)) {}
-
-  inline AlignedVector3(const AlignedVector3& other) : Base(), m_coeffs(other.m_coeffs) {}
-
-  template <typename XprType, int Size = XprType::SizeAtCompileTime>
-  struct generic_assign_selector {};
-
-  template <typename XprType>
-  struct generic_assign_selector<XprType, 4> {
-    inline static void run(AlignedVector3& dest, const XprType& src) { dest.m_coeffs = src; }
-  };
-
-  template <typename XprType>
-  struct generic_assign_selector<XprType, 3> {
-    inline static void run(AlignedVector3& dest, const XprType& src) {
-      dest.m_coeffs.template head<3>() = src;
-      dest.m_coeffs.w() = Scalar(0);
-    }
-  };
-
-  template <typename Derived>
-  inline AlignedVector3(const MatrixBase<Derived>& other) {
-    generic_assign_selector<Derived>::run(*this, other.derived());
-  }
-
-  inline AlignedVector3& operator=(const AlignedVector3& other) {
-    m_coeffs = other.m_coeffs;
-    return *this;
-  }
-
-  template <typename Derived>
-  inline AlignedVector3& operator=(const MatrixBase<Derived>& other) {
-    generic_assign_selector<Derived>::run(*this, other.derived());
-    return *this;
-  }
-
-  inline AlignedVector3 operator+(const AlignedVector3& other) const {
-    return AlignedVector3(m_coeffs + other.m_coeffs);
-  }
-
-  inline AlignedVector3& operator+=(const AlignedVector3& other) {
-    m_coeffs += other.m_coeffs;
-    return *this;
-  }
-
-  inline AlignedVector3 operator-(const AlignedVector3& other) const {
-    return AlignedVector3(m_coeffs - other.m_coeffs);
-  }
-
-  inline AlignedVector3 operator-() const { return AlignedVector3(-m_coeffs); }
-
-  inline AlignedVector3& operator-=(const AlignedVector3& other) {
-    m_coeffs -= other.m_coeffs;
-    return *this;
-  }
-
-  inline AlignedVector3 operator*(const Scalar& s) const { return AlignedVector3(m_coeffs * s); }
-
-  inline friend AlignedVector3 operator*(const Scalar& s, const AlignedVector3& vec) {
-    return AlignedVector3(s * vec.m_coeffs);
-  }
-
-  inline AlignedVector3& operator*=(const Scalar& s) {
-    m_coeffs *= s;
-    return *this;
-  }
-
-  inline AlignedVector3 operator/(const Scalar& s) const { return AlignedVector3(m_coeffs / s); }
-
-  inline AlignedVector3& operator/=(const Scalar& s) {
-    m_coeffs /= s;
-    return *this;
-  }
-
-  inline Scalar dot(const AlignedVector3& other) const {
-    eigen_assert(m_coeffs.w() == Scalar(0));
-    eigen_assert(other.m_coeffs.w() == Scalar(0));
-    return m_coeffs.dot(other.m_coeffs);
-  }
-
-  inline void normalize() { m_coeffs /= norm(); }
-
-  inline AlignedVector3 normalized() const { return AlignedVector3(m_coeffs / norm()); }
-
-  inline Scalar sum() const {
-    eigen_assert(m_coeffs.w() == Scalar(0));
-    return m_coeffs.sum();
-  }
-
-  inline Scalar squaredNorm() const {
-    eigen_assert(m_coeffs.w() == Scalar(0));
-    return m_coeffs.squaredNorm();
-  }
-
-  inline Scalar norm() const {
-    using std::sqrt;
-    return sqrt(squaredNorm());
-  }
-
-  inline AlignedVector3 cross(const AlignedVector3& other) const {
-    return AlignedVector3(m_coeffs.cross3(other.m_coeffs));
-  }
-
-  template <typename Derived>
-  inline bool isApprox(const MatrixBase<Derived>& other,
-                       const RealScalar& eps = NumTraits<Scalar>::dummy_precision()) const {
-    return m_coeffs.template head<3>().isApprox(other, eps);
-  }
-
-  CoeffType& coeffs() { return m_coeffs; }
-  const CoeffType& coeffs() const { return m_coeffs; }
-};
-
-namespace internal {
-
-template <typename Scalar_>
-struct eval<AlignedVector3<Scalar_>, Dense> {
-  typedef const AlignedVector3<Scalar_>& type;
-};
-
-template <typename Scalar>
-struct evaluator<AlignedVector3<Scalar> > : evaluator<Matrix<Scalar, 4, 1> > {
-  typedef AlignedVector3<Scalar> XprType;
-  typedef evaluator<Matrix<Scalar, 4, 1> > Base;
-
-  evaluator(const XprType& m) : Base(m.coeffs()) {}
-};
-
-}  // namespace internal
-
-//@}
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_ALIGNED_VECTOR3_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_ALIGNEDVECTOR3_FORWARD_H
diff --git a/unsupported/Eigen/ArpackSupport b/unsupported/Eigen/ArpackSupport
index 16aca7c..c1f7e77 100644
--- a/unsupported/Eigen/ArpackSupport
+++ b/unsupported/Eigen/ArpackSupport
@@ -1,35 +1,17 @@
 // 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/ArpackSupport>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_ARPACKSUPPORT_MODULE_H
-#define EIGEN_ARPACKSUPPORT_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_ARPACKSUPPORT_FORWARD_H
+#define EIGEN_UNSUPPORTED_ARPACKSUPPORT_FORWARD_H
 
-#include "../../Eigen/Core"
+#include "../../contrib/Eigen/ArpackSupport"  // IWYU pragma: export
 
-/** \defgroup ArpackSupport_Module Arpack support module
- *
- * This module provides a wrapper to Arpack, a library for sparse eigenvalue decomposition.
- *
- * \code
- * #include <unsupported/Eigen/ArpackSupport>
- * \endcode
- */
-
-#include "../../Eigen/SparseCholesky"
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/ArpackSupport/ArpackSelfAdjointEigenSolver.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_ARPACKSUPPORT_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_ARPACKSUPPORT_FORWARD_H
diff --git a/unsupported/Eigen/AutoDiff b/unsupported/Eigen/AutoDiff
index 5466c54..13918d2 100644
--- a/unsupported/Eigen/AutoDiff
+++ b/unsupported/Eigen/AutoDiff
@@ -1,50 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/AutoDiff>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_AUTODIFF_MODULE_H
-#define EIGEN_AUTODIFF_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_AUTODIFF_FORWARD_H
+#define EIGEN_UNSUPPORTED_AUTODIFF_FORWARD_H
 
-#include "../../Eigen/Core"
+#include "../../contrib/Eigen/AutoDiff"  // IWYU pragma: export
 
-namespace Eigen {
-
-/**
- * \defgroup AutoDiff_Module Auto Diff module
- *
- * This module features forward automatic differentiation via a simple
- * templated scalar type wrapper AutoDiffScalar.
- *
- * Warning : this should NOT be confused with numerical differentiation, which
- * is a different method and has its own module in Eigen : \ref NumericalDiff_Module.
- *
- * \code
- * #include <unsupported/Eigen/AutoDiff>
- * \endcode
- *
- * See \ref AutoDiffExamples for introductory examples.
- */
-//@{
-
-}  // namespace Eigen
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/AutoDiff/CoherentPadOp.h"
-#include "src/AutoDiff/AutoDiffScalar.h"
-#include "src/AutoDiff/AutoDiffJacobian.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-namespace Eigen {
-//@}
-}
-
-#endif  // EIGEN_AUTODIFF_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_AUTODIFF_FORWARD_H
diff --git a/unsupported/Eigen/BVH b/unsupported/Eigen/BVH
index 15b0883..c6cd8e9 100644
--- a/unsupported/Eigen/BVH
+++ b/unsupported/Eigen/BVH
@@ -1,113 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/BVH>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_BVH_MODULE_H
-#define EIGEN_BVH_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_BVH_FORWARD_H
+#define EIGEN_UNSUPPORTED_BVH_FORWARD_H
 
-#include "../../Eigen/Core"
-#include "../../Eigen/Geometry"
-#include "../../Eigen/StdVector"
-#include <algorithm>
-#include <queue>
+#include "../../contrib/Eigen/BVH"  // IWYU pragma: export
 
-namespace Eigen {
-
-/**
-  * \defgroup BVH_Module BVH module
-  * \brief This module provides generic bounding volume hierarchy algorithms
-  * and reference tree implementations.
-  *
-  *
-  * \code
-  * #include <unsupported/Eigen/BVH>
-  * \endcode
-  *
-  * A bounding volume hierarchy (BVH) can accelerate many geometric queries.  This module provides a generic
-  implementation
-  * of the two basic algorithms over a BVH: intersection of a query object against all objects in the hierarchy and
-  minimization
-  * of a function over the objects in the hierarchy.  It also provides intersection and minimization over a cartesian
-  product of
-  * two BVH's.  A BVH accelerates intersection by using the fact that if a query object does not intersect a volume,
-  then it cannot
-  * intersect any object contained in that volume.  Similarly, a BVH accelerates minimization because the minimum of a
-  function
-  * over a volume is no greater than the minimum of a function over any object contained in it.
-  *
-  * Some sample queries that can be written in terms of intersection are:
-  *   - Determine all points where a ray intersects a triangle mesh
-  *   - Given a set of points, determine which are contained in a query sphere
-  *   - Given a set of spheres, determine which contain the query point
-  *   - Given a set of disks, determine if any is completely contained in a query rectangle (represent each 2D disk as a
-  point \f$(x,y,r)\f$
-  *     in 3D and represent the rectangle as a pyramid based on the original rectangle and shrinking in the \f$r\f$
-  direction)
-  *   - Given a set of points, count how many pairs are \f$d\pm\epsilon\f$ apart (done by looking at the cartesian
-  product of the set
-  *     of points with itself)
-  *
-  * Some sample queries that can be written in terms of function minimization over a set of objects are:
-  *   - Find the intersection between a ray and a triangle mesh closest to the ray origin (function is infinite off the
-  ray)
-  *   - Given a polyline and a query point, determine the closest point on the polyline to the query
-  *   - Find the diameter of a point cloud (done by looking at the cartesian product and using negative distance as the
-  function)
-  *   - Determine how far two meshes are from colliding (this is also a cartesian product query)
-  *
-  * This implementation decouples the basic algorithms both from the type of hierarchy (and the types of the bounding
-  volumes) and
-  * from the particulars of the query.  To enable abstraction from the BVH, the BVH is required to implement a generic
-  mechanism
-  * for traversal.  To abstract from the query, the query is responsible for keeping track of results.
-  *
-  * To be used in the algorithms, a hierarchy must implement the following traversal mechanism (see KdBVH for a sample
-  implementation): \code typedef Volume  //the type of bounding volume typedef Object  //the type of object in the
-  hierarchy typedef Index   //a reference to a node in the hierarchy--typically an int or a pointer typedef
-  VolumeIterator //an iterator type over node children--returns Index typedef ObjectIterator //an iterator over object
-  (leaf) children--returns const Object & Index getRootIndex() const //returns the index of the hierarchy root const
-  Volume &getVolume(Index index) const //returns the bounding volume of the node at given index void getChildren(Index
-  index, VolumeIterator &outVBegin, VolumeIterator &outVEnd, ObjectIterator &outOBegin, ObjectIterator &outOEnd) const
-      //getChildren takes a node index and makes [outVBegin, outVEnd) range over its node children
-      //and [outOBegin, outOEnd) range over its object children
-    \endcode
-  *
-  * To use the hierarchy, call BVIntersect or BVMinimize, passing it a BVH (or two, for cartesian product) and a
-  minimizer or intersector.
-  * For an intersection query on a single BVH, the intersector encapsulates the query and must provide two functions:
-  * \code
-      bool intersectVolume(const Volume &volume) //returns true if the query intersects the volume
-      bool intersectObject(const Object &object) //returns true if the intersection search should terminate immediately
-    \endcode
-  * The guarantee that BVIntersect provides is that intersectObject will be called on every object whose bounding volume
-  * intersects the query (but possibly on other objects too) unless the search is terminated prematurely.  It is the
-  * responsibility of the intersectObject function to keep track of the results in whatever manner is appropriate.
-  * The cartesian product intersection and the BVMinimize queries are similar--see their individual documentation.
-  *
-  * The following is a simple but complete example for how to use the BVH to accelerate the search for a closest
-  red-blue point pair:
-  * \include BVH_Example.cpp
-  * Output: \verbinclude BVH_Example.out
-  */
-}
-
-//@{
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/BVH/BVAlgorithms.h"
-#include "src/BVH/KdBVH.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-//@}
-
-#endif  // EIGEN_BVH_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_BVH_FORWARD_H
diff --git a/unsupported/Eigen/CMakeLists.txt b/unsupported/Eigen/CMakeLists.txt
index e2c01af..c6620e5 100644
--- a/unsupported/Eigen/CMakeLists.txt
+++ b/unsupported/Eigen/CMakeLists.txt
@@ -1,7 +1,10 @@
 # SPDX-FileCopyrightText: The Eigen Authors
 # SPDX-License-Identifier: MPL-2.0
+#
+# Forwarding shims for the legacy <unsupported/Eigen/...> include paths.
+# The actual module headers live under ../../contrib/Eigen/.
 
-set(Eigen_HEADERS
+set(Eigen_LegacyShim_HEADERS
   AdolcForward
   AlignedVector3
   ArpackSupport
@@ -31,11 +34,9 @@
 
 if(EIGEN_INSTALL)
   install(FILES
-    ${Eigen_HEADERS}
+    ${Eigen_LegacyShim_HEADERS}
     DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen COMPONENT Devel
     )
-
-  install(DIRECTORY src DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen COMPONENT Devel FILES_MATCHING PATTERN "*.h")
 endif()
 
 add_subdirectory(CXX11)
diff --git a/unsupported/Eigen/CXX11/CMakeLists.txt b/unsupported/Eigen/CXX11/CMakeLists.txt
index ae151dc..b538799 100644
--- a/unsupported/Eigen/CXX11/CMakeLists.txt
+++ b/unsupported/Eigen/CXX11/CMakeLists.txt
@@ -1,11 +1,17 @@
-# Forwarding headers for backward compatibility.
 # SPDX-FileCopyrightText: The Eigen Authors
 # SPDX-License-Identifier: MPL-2.0
-set(Eigen_CXX11_HEADERS Tensor TensorSymmetry ThreadPool)
+#
+# Forwarding shims for the legacy <unsupported/Eigen/CXX11/...> include paths.
+
+set(Eigen_LegacyShim_CXX11_HEADERS
+  Tensor
+  TensorSymmetry
+  ThreadPool
+  )
 
 if(EIGEN_INSTALL)
   install(FILES
-    ${Eigen_CXX11_HEADERS}
+    ${Eigen_LegacyShim_CXX11_HEADERS}
     DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen/CXX11 COMPONENT Devel
     )
 endif()
diff --git a/unsupported/Eigen/CXX11/Tensor b/unsupported/Eigen/CXX11/Tensor
index c07ee6f..2d5fda4 100644
--- a/unsupported/Eigen/CXX11/Tensor
+++ b/unsupported/Eigen/CXX11/Tensor
@@ -1,7 +1,15 @@
-// Forwarding header for backward compatibility.
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x, and the CXX11/ subdirectory no longer
+// exists at the new location. New code should use
+//   #include <contrib/Eigen/Tensor>
+// directly. This shim preserves the legacy include path.
 
 // Forward every inclusion so the Tensor module can detect a newly enabled
 // backend and complete its device type.
-#include "../Tensor"  // IWYU pragma: export
+#include "../../../contrib/Eigen/Tensor"  // IWYU pragma: export
diff --git a/unsupported/Eigen/CXX11/TensorSymmetry b/unsupported/Eigen/CXX11/TensorSymmetry
index d9513b8..0e49eba 100644
--- a/unsupported/Eigen/CXX11/TensorSymmetry
+++ b/unsupported/Eigen/CXX11/TensorSymmetry
@@ -1,10 +1,18 @@
-// Forwarding header for backward compatibility.
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x, and the CXX11/ subdirectory no longer
+// exists at the new location. New code should use
+//   #include <contrib/Eigen/TensorSymmetry>
+// directly. This shim preserves the legacy include path.
 
 #ifndef EIGEN_UNSUPPORTED_CXX11_TENSORSYMMETRY_FORWARD_H
 #define EIGEN_UNSUPPORTED_CXX11_TENSORSYMMETRY_FORWARD_H
 
-#include "../TensorSymmetry"  // IWYU pragma: export
+#include "../../../contrib/Eigen/TensorSymmetry"  // IWYU pragma: export
 
 #endif  // EIGEN_UNSUPPORTED_CXX11_TENSORSYMMETRY_FORWARD_H
diff --git a/unsupported/Eigen/CXX11/ThreadPool b/unsupported/Eigen/CXX11/ThreadPool
index 703791b..1162513 100644
--- a/unsupported/Eigen/CXX11/ThreadPool
+++ b/unsupported/Eigen/CXX11/ThreadPool
@@ -1,10 +1,17 @@
-// Forwarding header for backward compatibility.
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: ThreadPool was promoted to a core Eigen module in
+// Eigen 5.x. New code should use
+//   #include <Eigen/ThreadPool>
+// directly. This shim preserves the legacy include path.
 
 #ifndef EIGEN_UNSUPPORTED_CXX11_THREADPOOL_FORWARD_H
 #define EIGEN_UNSUPPORTED_CXX11_THREADPOOL_FORWARD_H
 
-#include "../ThreadPool"  // IWYU pragma: export
+#include "../../../Eigen/ThreadPool"  // IWYU pragma: export
 
 #endif  // EIGEN_UNSUPPORTED_CXX11_THREADPOOL_FORWARD_H
diff --git a/unsupported/Eigen/EulerAngles b/unsupported/Eigen/EulerAngles
index 3c794a6..bfba8fa 100644
--- a/unsupported/Eigen/EulerAngles
+++ b/unsupported/Eigen/EulerAngles
@@ -1,45 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2015 Tal Hadad <tal_hd@hotmail.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-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/EulerAngles>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_EULERANGLES_MODULE_H
-#define EIGEN_EULERANGLES_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_EULERANGLES_FORWARD_H
+#define EIGEN_UNSUPPORTED_EULERANGLES_FORWARD_H
 
-#include "../../Eigen/Core"
-#include "../../Eigen/Geometry"
+#include "../../contrib/Eigen/EulerAngles"  // IWYU pragma: export
 
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/**
- * \defgroup EulerAngles_Module EulerAngles module
- * \brief This module provides generic euler angles rotation.
- *
- * Euler angles are a way to represent 3D rotation.
- *
- * In order to use this module in your code, include this header:
- * \code
- * #include <unsupported/Eigen/EulerAngles>
- * \endcode
- *
- * See \ref EulerAngles for more information.
- *
- */
-
-}
-
-// IWYU pragma: begin_exports
-#include "src/EulerAngles/EulerSystem.h"
-#include "src/EulerAngles/EulerAngles.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_EULERANGLES_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_EULERANGLES_FORWARD_H
diff --git a/unsupported/Eigen/FFT b/unsupported/Eigen/FFT
index 43ee3dc..3190a9d 100644
--- a/unsupported/Eigen/FFT
+++ b/unsupported/Eigen/FFT
@@ -1,494 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Mark Borgerding mark a borgerding net
-//
-// 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
-
-#ifndef EIGEN_FFT_MODULE_H
-#define EIGEN_FFT_MODULE_H
-
-#include <complex>
-#include <vector>
-#include <map>
-#include "../../Eigen/Core"
-
-/**
- * \defgroup FFT_Module Fast Fourier Transform module
- *
- * \code
- * #include <unsupported/Eigen/FFT>
- * \endcode
- *
- * This module provides Fast Fourier transformation, with a configurable backend
- * implementation.
- *
- * The default implementation is based on kissfft. It is a small, free, and
- * reasonably efficient default.
- *
- * There are currently four implementation backend:
- *
- * - kissfft(https://github.com/mborgerding/kissfft) : Simple and not so fast, BSD-3-Clause.
- *   It is a mixed-radix Fast Fourier Transform based up on the principle, "Keep It Simple, Stupid."
- *   Notice that:kissfft fails to handle "atypically-sized" inputs(i.e., sizes with large factors),a workaround is using
- * fftw or pocketfft.
- * - fftw (http://www.fftw.org) : faster, GPL -- incompatible with Eigen in LGPL form, bigger code size.
- * - MKL (https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl-download.html) : fastest, free -- may be
- * incompatible with Eigen in GPL form.
- * - PocketFFT/DUCC (https://gitlab.mpcdf.mpg.de/mtr/pocketfft, https://gitlab.mpcdf.mpg.de/mtr/ducc) : faster than
- *   kissfft, BSD 3-clause. A heavily modified implementation of FFTPack with the following advantages:
- *   -# strictly C++14 compliant
- *   -# more accurate twiddle factor computation
- *   -# very fast plan generation
- *   -# worst case complexity for transform sizes with large prime factors is N*log(N),
- *      because Bluestein's algorithm is used for these cases.
- *   .
- *   According to the author, DUCC contains the "evolution" of pocketfft, though the interface is very similar.
- *
- * \section FFTThreadSafety Thread safety
- *
- * An FFT object is not thread-safe: it caches a plan, so concurrent transforms need one object per
- * thread. Distinct objects may be used concurrently.
- *
- * That is not by itself enough for the FFTW backend, whose planner keeps process-wide state and
- * whose only concurrent entry points are \c fftw_execute and its new-array variants. %Eigen
- * therefore serializes plan creation and destruction on a mutex of its own, which covers every
- * planner call %Eigen makes from within one process image.
- *
- * Two cases fall outside that. FFTW planner calls made directly, not through %Eigen, share nothing
- * with %Eigen's mutex. And a program that loads several shared libraries which each carry their own
- * copy of %Eigen may end up with one mutex per library instead of one per process: %Eigen gives the
- * mutex default visibility so that the dynamic linker collapses those copies, which covers ELF
- * libraries linked normally or loaded with \c RTLD_GLOBAL, but not separate Windows DLLs, and not a
- * library loaded with \c RTLD_LOCAL unless the compiler emitted a unique symbol for the definition.
- * In either case, call FFTW's own \c fftw_make_planner_thread_safe() once before any transform: it
- * puts the lock inside the planner, where it applies to every caller. It needs FFTW 3.3.5 or later,
- * built with thread support.
- *
- * \section FFTDesign Design
- *
- * The following design decisions were made concerning scaling and
- * half-spectrum for real FFT.
- *
- * The intent is to facilitate generic programming and ease migrating code
- * from  Matlab/octave.
- * We think the default behavior of Eigen/FFT should favor correctness and
- * generality over speed. Of course, the caller should be able to "opt-out" from this
- * behavior and get the speed increase if they want it.
- *
- * 1) %Scaling:
- * Other libraries (FFTW,IMKL,KISSFFT)  do not perform scaling, so there
- * is a constant gain incurred after the forward&inverse transforms , so
- * IFFT(FFT(x)) = Kx;  this is done to avoid a vector-by-value multiply.
- * The downside is that algorithms that worked correctly in Matlab/octave
- * don't behave the same way once implemented in C++.
- *
- * How Eigen/FFT differs: invertible scaling is performed so IFFT( FFT(x) ) = x.
- *
- * 2) Real FFT half-spectrum
- * Other libraries use only half the frequency spectrum (plus one extra
- * sample for the Nyquist bin) for a real FFT, the other half is the
- * conjugate-symmetric of the first half.  This saves them a copy and some
- * memory.  The downside is the caller needs to have special logic for the
- * number of bins in complex vs real.
- *
- * How Eigen/FFT differs: The full spectrum is returned from the forward
- * transform.  This facilitates generic template programming by obviating
- * separate specializations for real vs complex.  On the inverse
- * transform, only half the spectrum is actually used if the output type is real.
- */
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-
-#ifdef EIGEN_FFTW_DEFAULT
-// FFTW: faster, GPL -- incompatible with Eigen in LGPL form, bigger code size
-#include <fftw3.h>
-#include "src/FFT/fftw_impl.h"
-namespace Eigen {
-template <typename T>
-struct default_fft_impl : public internal::fftw_impl<T> {};
-}  // namespace Eigen
-#elif defined EIGEN_MKL_DEFAULT
-// intel Math Kernel Library: fastest, free -- may be incompatible with Eigen in GPL form
-#include "src/FFT/imklfft_impl.h"
-namespace Eigen {
-template <typename T>
-struct default_fft_impl : public internal::imklfft::imklfft_impl<T> {};
-}  // namespace Eigen
-#elif defined EIGEN_POCKETFFT_DEFAULT
-// internal::pocketfft_impl: a heavily modified implementation of FFTPack, with many advantages.
-#include <pocketfft_hdronly.h>
-#include "src/FFT/pocketfft_impl.h"
-namespace Eigen {
-template <typename T>
-struct default_fft_impl : public internal::pocketfft_impl<T> {};
-}  // namespace Eigen
-#elif defined EIGEN_DUCCFFT_DEFAULT
-#include <ducc0/fft/fft.h>
-#include <ducc0/infra/string_utils.h>
-#include <ducc0/fft/fftnd_impl.h>
-#include "src/FFT/duccfft_impl.h"
-namespace Eigen {
-template <typename T>
-struct default_fft_impl : public internal::duccfft_impl<T> {};
-}  // namespace Eigen
-#else
-// internal::kissfft_impl:  small, free, reasonably efficient default, derived from kissfft
-#include "src/FFT/kissfft_impl.h"
-namespace Eigen {
-template <typename T>
-struct default_fft_impl : public internal::kissfft_impl<T> {};
-}  // namespace Eigen
-#endif
-
-// IWYU pragma: end_exports
-
-namespace Eigen {
-
 //
-template <typename T_SrcMat, typename T_FftIfc>
-struct fft_fwd_proxy;
-template <typename T_SrcMat, typename T_FftIfc>
-struct fft_inv_proxy;
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/FFT>
+// directly. This shim preserves the legacy include path.
 
-namespace internal {
-template <typename T_SrcMat, typename T_FftIfc>
-struct traits<fft_fwd_proxy<T_SrcMat, T_FftIfc> > {
-  typedef typename T_SrcMat::PlainObject ReturnType;
-};
-template <typename T_SrcMat, typename T_FftIfc>
-struct traits<fft_inv_proxy<T_SrcMat, T_FftIfc> > {
-  typedef typename T_SrcMat::PlainObject ReturnType;
-};
-}  // namespace internal
+#ifndef EIGEN_UNSUPPORTED_FFT_FORWARD_H
+#define EIGEN_UNSUPPORTED_FFT_FORWARD_H
 
-template <typename T_SrcMat, typename T_FftIfc>
-struct fft_fwd_proxy : public ReturnByValue<fft_fwd_proxy<T_SrcMat, T_FftIfc> > {
-  typedef Eigen::Index Index;
+#include "../../contrib/Eigen/FFT"  // IWYU pragma: export
 
-  fft_fwd_proxy(const T_SrcMat& src, T_FftIfc& fft, Index nfft) : m_src(src), m_ifc(fft), m_nfft(nfft) {}
-
-  template <typename T_DestMat>
-  void evalTo(T_DestMat& dst) const;
-
-  Index rows() const { return m_src.rows(); }
-  Index cols() const { return m_src.cols(); }
-
- protected:
-  const T_SrcMat& m_src;
-  T_FftIfc& m_ifc;
-  Index m_nfft;
-};
-
-template <typename T_SrcMat, typename T_FftIfc>
-struct fft_inv_proxy : public ReturnByValue<fft_inv_proxy<T_SrcMat, T_FftIfc> > {
-  typedef Eigen::Index Index;
-
-  fft_inv_proxy(const T_SrcMat& src, T_FftIfc& fft, Index nfft) : m_src(src), m_ifc(fft), m_nfft(nfft) {}
-
-  template <typename T_DestMat>
-  void evalTo(T_DestMat& dst) const;
-
-  Index rows() const { return m_src.rows(); }
-  Index cols() const { return m_src.cols(); }
-
- protected:
-  const T_SrcMat& m_src;
-  T_FftIfc& m_ifc;
-  Index m_nfft;
-};
-
-namespace internal {
-
-// The transforms are one-dimensional, but a matrix with a dynamic dimension only knows at run
-// time whether that dimension is one, so it cannot be rejected at compile time the way a matrix
-// of known two-dimensional shape can. Only the latter is excluded here.
-template <typename Derived>
-struct fft_accepts_as_vector {
-  static constexpr bool value = bool(Derived::IsVectorAtCompileTime) || int(Derived::RowsAtCompileTime) == Dynamic ||
-                                int(Derived::ColsAtCompileTime) == Dynamic;
-};
-
-// Distance between consecutive elements of a one-dimensional operand. The inner stride does not
-// answer this once matrices are accepted: a matrix holding a single row steps along its outer
-// stride, and only a unit distance lets the transform run over the operand's own memory.
-template <typename Derived>
-EIGEN_STRONG_INLINE Index fft_linear_stride(const DenseBase<Derived>& x) {
-  return x.rows() == 1 ? x.derived().colStride() : x.derived().rowStride();
-}
-
-// Resize a one-dimensional destination. Every orientation a compile-time dimension leaves open
-// is settled here: a fixed dimension other than one can only be the long one, and a destination
-// with two dynamic dimensions takes the orientation of the source.
-template <typename Derived>
-EIGEN_STRONG_INLINE void fft_resize_as_vector(DenseBase<Derived>& dst, Index size, bool source_is_row) {
-  // A destination already holding the transform's length in one dimension keeps that shape, which
-  // is the only one a view such as a Map can be given at all.
-  if ((dst.rows() == 1 && dst.cols() == size) || (dst.cols() == 1 && dst.rows() == size)) return;
-
-  constexpr int Rows = int(Derived::RowsAtCompileTime);
-  constexpr int Cols = int(Derived::ColsAtCompileTime);
-  const bool row = Rows == 1         ? true
-                   : Cols == 1       ? false
-                   : Cols != Dynamic ? true
-                   : Rows != Dynamic ? false
-                                     : source_is_row;
-  dst.derived().resize(row ? 1 : size, row ? size : 1);
-}
-
-}  // namespace internal
-
-#define EIGEN_STATIC_ASSERT_FFT_VECTOR(TYPE) \
-  EIGEN_STATIC_ASSERT(internal::fft_accepts_as_vector<TYPE>::value, YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX)
-
-template <typename T_Scalar, typename T_Impl = default_fft_impl<T_Scalar> >
-class FFT {
- public:
-  typedef T_Impl impl_type;
-  typedef Eigen::Index Index;
-  typedef typename impl_type::Scalar Scalar;
-  typedef typename impl_type::Complex Complex;
-
-  using Flag = int;
-  static constexpr Flag Default = 0;
-  static constexpr Flag Unscaled = 1;
-  static constexpr Flag HalfSpectrum = 2;
-  static constexpr Flag Speedy = 32767;
-
-  FFT(const impl_type& impl = impl_type(), Flag flags = Default) : m_impl(impl), m_flag(flags) {
-    eigen_assert((flags == Default || flags == Unscaled || flags == HalfSpectrum || flags == Speedy) &&
-                 "invalid flags argument");
-  }
-
-  inline bool HasFlag(Flag f) const { return (m_flag & (int)f) == f; }
-
-  inline void SetFlag(Flag f) { m_flag |= (int)f; }
-
-  inline void ClearFlag(Flag f) { m_flag &= (~(int)f); }
-
-  inline void fwd(Complex* dst, const Scalar* src, Index nfft) {
-    m_impl.fwd(dst, src, static_cast<int>(nfft));
-    if (HasFlag(HalfSpectrum) == false) ReflectSpectrum(dst, nfft);
-  }
-
-  inline void fwd(Complex* dst, const Complex* src, Index nfft) { m_impl.fwd(dst, src, static_cast<int>(nfft)); }
-
-#if defined EIGEN_FFTW_DEFAULT || defined EIGEN_POCKETFFT_DEFAULT || defined EIGEN_DUCCFFT_DEFAULT || \
-    defined EIGEN_MKL_DEFAULT
-  inline void fwd2(Complex* dst, const Complex* src, int n0, int n1) { m_impl.fwd2(dst, src, n0, n1); }
-#endif
-
-  template <typename Input_>
-  inline void fwd(std::vector<Complex>& dst, const std::vector<Input_>& src) {
-    EIGEN_IF_CONSTEXPR (NumTraits<Input_>::IsComplex == 0) {
-      if (HasFlag(HalfSpectrum))
-        dst.resize((src.size() >> 1) + 1);  // half the bins + Nyquist bin
-      else
-        dst.resize(src.size());
-    } else {
-      dst.resize(src.size());
-    }
-    fwd(&dst[0], &src[0], src.size());
-  }
-
-  template <typename InputDerived, typename ComplexDerived>
-  inline void fwd(DenseBase<ComplexDerived>& dst, const DenseBase<InputDerived>& src, Index nfft = -1) {
-    typedef typename ComplexDerived::Scalar dst_type;
-    typedef typename InputDerived::Scalar src_type;
-    EIGEN_STATIC_ASSERT_FFT_VECTOR(InputDerived)
-    EIGEN_STATIC_ASSERT_FFT_VECTOR(ComplexDerived)
-    EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived, InputDerived)  // size at compile-time
-    EIGEN_STATIC_ASSERT(
-        (std::is_same<dst_type, Complex>::value),
-        YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-    EIGEN_STATIC_ASSERT(int(InputDerived::Flags) & int(ComplexDerived::Flags) & DirectAccessBit,
-                        THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
-    eigen_assert((src.rows() == 1 || src.cols() == 1) && "the input of an FFT must be one-dimensional");
-
-    if (nfft < 1) nfft = src.size();
-
-    Index dst_size = nfft;
-    EIGEN_IF_CONSTEXPR (NumTraits<src_type>::IsComplex == 0) {
-      if (HasFlag(HalfSpectrum)) {
-        dst_size = (nfft >> 1) + 1;
-      }
-    }
-    internal::fft_resize_as_vector(dst, dst_size, src.rows() == 1);
-
-    if (internal::fft_linear_stride(src) != 1 || src.size() < nfft) {
-      Matrix<src_type, 1, Dynamic> tmp(1, nfft);
-      const Index copy_size = (std::min)(src.size(), nfft);
-      if (copy_size > 0) {
-        tmp.head(copy_size) = src.reshaped().head(copy_size);
-      }
-      if (copy_size < nfft) tmp.tail(nfft - copy_size).setZero();
-      if (internal::fft_linear_stride(dst) != 1) {
-        Matrix<dst_type, 1, Dynamic> out(1, dst_size);
-        fwd(out.data(), tmp.data(), nfft);
-        dst.derived() = out.reshaped(dst.rows(), dst.cols());
-      } else {
-        fwd(dst.derived().data(), tmp.data(), nfft);
-      }
-    } else {
-      if (internal::fft_linear_stride(dst) != 1) {
-        Matrix<dst_type, 1, Dynamic> out(1, dst_size);
-        fwd(out.data(), src.derived().data(), nfft);
-        dst.derived() = out.reshaped(dst.rows(), dst.cols());
-      } else {
-        fwd(dst.derived().data(), src.derived().data(), nfft);
-      }
-    }
-  }
-
-  template <typename InputDerived>
-  inline fft_fwd_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> > fwd(const DenseBase<InputDerived>& src,
-                                                                            Index nfft = -1) {
-    return fft_fwd_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> >(src, *this, nfft);
-  }
-
-  template <typename InputDerived>
-  inline fft_inv_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> > inv(const DenseBase<InputDerived>& src,
-                                                                            Index nfft = -1) {
-    return fft_inv_proxy<DenseBase<InputDerived>, FFT<T_Scalar, T_Impl> >(src, *this, nfft);
-  }
-
-  inline void inv(Complex* dst, const Complex* src, Index nfft) {
-    m_impl.inv(dst, src, static_cast<int>(nfft));
-    if (HasFlag(Unscaled) == false) scale(dst, Scalar(1. / nfft), nfft);  // scale the time series
-  }
-
-  inline void inv(Scalar* dst, const Complex* src, Index nfft) {
-    m_impl.inv(dst, src, static_cast<int>(nfft));
-    if (HasFlag(Unscaled) == false) scale(dst, Scalar(1. / nfft), nfft);  // scale the time series
-  }
-
-  template <typename OutputDerived, typename ComplexDerived>
-  inline void inv(DenseBase<OutputDerived>& dst, const DenseBase<ComplexDerived>& src, Index nfft = -1) {
-    typedef typename ComplexDerived::Scalar src_type;
-    typedef typename ComplexDerived::RealScalar real_type;
-    typedef typename OutputDerived::Scalar dst_type;
-    const bool realfft = (NumTraits<dst_type>::IsComplex == 0);
-    EIGEN_STATIC_ASSERT_FFT_VECTOR(OutputDerived)
-    EIGEN_STATIC_ASSERT_FFT_VECTOR(ComplexDerived)
-    EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived, OutputDerived)  // size at compile-time
-    EIGEN_STATIC_ASSERT(
-        (std::is_same<src_type, Complex>::value),
-        YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-    EIGEN_STATIC_ASSERT(int(OutputDerived::Flags) & int(ComplexDerived::Flags) & DirectAccessBit,
-                        THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
-    eigen_assert((src.rows() == 1 || src.cols() == 1) && "the input of an FFT must be one-dimensional");
-
-    if (nfft < 1) {  // automatic FFT size determination
-      if (realfft && HasFlag(HalfSpectrum))
-        nfft = 2 * (src.size() - 1);  // assume even fft size
-      else
-        nfft = src.size();
-    }
-    internal::fft_resize_as_vector(dst, nfft, src.rows() == 1);
-
-    // check for nfft that does not fit the input data size
-    Index resize_input = (realfft && HasFlag(HalfSpectrum)) ? ((nfft / 2 + 1) - src.size()) : (nfft - src.size());
-
-    if (internal::fft_linear_stride(src) != 1 || resize_input) {
-      // if the vector is strided, then we need to copy it to a packed temporary
-      const auto src_lin = src.reshaped();
-      Matrix<src_type, 1, Dynamic> tmp;
-      if (resize_input) {
-        size_t ncopy = (std::min)(src.size(), src.size() + resize_input);
-        tmp.setZero(src.size() + resize_input);
-        if (realfft && HasFlag(HalfSpectrum)) {
-          // pad at the Nyquist bin
-          tmp.head(ncopy) = src_lin.head(ncopy);
-          tmp(ncopy - 1) = real(tmp(ncopy - 1));  // enforce real-only Nyquist bin
-        } else {
-          size_t nhead, ntail;
-          nhead = 1 + ncopy / 2 - 1;  // range  [0:pi)
-          ntail = ncopy / 2 - 1;      // range (-pi:0)
-          tmp.head(nhead) = src_lin.head(nhead);
-          tmp.tail(ntail) = src_lin.tail(ntail);
-          if (resize_input <
-              0) {  // shrinking -- create the Nyquist bin as the average of the two bins that fold into it
-            tmp(nhead) = (src_lin(nfft / 2) + src_lin(src.size() - nfft / 2)) * real_type(.5);
-          } else {  // expanding -- split the old Nyquist bin into two halves
-            tmp(nhead) = src_lin(nhead) * real_type(.5);
-            tmp(tmp.size() - nhead) = tmp(nhead);
-          }
-        }
-      } else {
-        tmp = src_lin;
-      }
-
-      if (internal::fft_linear_stride(dst) != 1) {
-        Matrix<dst_type, 1, Dynamic> out(1, nfft);
-        inv(out.data(), tmp.data(), nfft);
-        dst.derived() = out.reshaped(dst.rows(), dst.cols());
-      } else {
-        inv(dst.derived().data(), tmp.data(), nfft);
-      }
-    } else {
-      if (internal::fft_linear_stride(dst) != 1) {
-        Matrix<dst_type, 1, Dynamic> out(1, nfft);
-        inv(out.data(), src.derived().data(), nfft);
-        dst.derived() = out.reshaped(dst.rows(), dst.cols());
-      } else {
-        inv(dst.derived().data(), src.derived().data(), nfft);
-      }
-    }
-  }
-
-  template <typename Output_>
-  inline void inv(std::vector<Output_>& dst, const std::vector<Complex>& src, Index nfft = -1) {
-    if (nfft < 1)
-      nfft = (NumTraits<Output_>::IsComplex == 0 && HasFlag(HalfSpectrum)) ? 2 * (src.size() - 1) : src.size();
-    dst.resize(nfft);
-    inv(&dst[0], &src[0], nfft);
-  }
-
-#if defined EIGEN_FFTW_DEFAULT || defined EIGEN_POCKETFFT_DEFAULT || defined EIGEN_DUCCFFT_DEFAULT || \
-    defined EIGEN_MKL_DEFAULT
-  inline void inv2(Complex* dst, const Complex* src, int n0, int n1) {
-    m_impl.inv2(dst, src, n0, n1);
-    if (HasFlag(Unscaled) == false) scale(dst, Scalar(1) / (n0 * n1), n0 * n1);
-  }
-#endif
-
-  inline impl_type& impl() { return m_impl; }
-
- private:
-  template <typename T_Data>
-  inline void scale(T_Data* x, Scalar s, Index nx) {
-    for (int k = 0; k < nx; ++k) *x++ *= s;
-  }
-
-  inline void ReflectSpectrum(Complex* freq, Index nfft) {
-    // create the implicit right-half spectrum (conjugate-mirror of the left-half)
-    Index nhbins = (nfft >> 1) + 1;
-    for (Index k = nhbins; k < nfft; ++k) freq[k] = conj(freq[nfft - k]);
-  }
-
-  impl_type m_impl;
-  int m_flag;
-};
-
-template <typename T_SrcMat, typename T_FftIfc>
-template <typename T_DestMat>
-inline void fft_fwd_proxy<T_SrcMat, T_FftIfc>::evalTo(T_DestMat& dst) const {
-  m_ifc.fwd(dst, m_src, m_nfft);
-}
-
-template <typename T_SrcMat, typename T_FftIfc>
-template <typename T_DestMat>
-inline void fft_inv_proxy<T_SrcMat, T_FftIfc>::evalTo(T_DestMat& dst) const {
-  m_ifc.inv(dst, m_src, m_nfft);
-}
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_FFT_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_FFT_FORWARD_H
diff --git a/unsupported/Eigen/GPU b/unsupported/Eigen/GPU
index 4128fd9..e567d94 100644
--- a/unsupported/Eigen/GPU
+++ b/unsupported/Eigen/GPU
@@ -1,79 +1,17 @@
 // 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/GPU>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_GPU_MODULE_H
-#define EIGEN_GPU_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_GPU_FORWARD_H
+#define EIGEN_UNSUPPORTED_GPU_FORWARD_H
 
-#include "../../Eigen/Core"
-#include "../../Eigen/SparseCore"
+#include "../../contrib/Eigen/GPU"  // IWYU pragma: export
 
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-/** \defgroup GPU_Module GPU module
- *
- * GPU-accelerated dense linear algebra using NVIDIA CUDA libraries
- * (cuSOLVER and cuBLAS).
- *
- * This module provides explicit GPU solver classes that coexist with Eigen's
- * CPU solvers. Unlike the LAPACKE dispatch (which replaces the CPU
- * implementation globally), GPU classes are separate types the user
- * instantiates by choice:
- *
- * \code
- * #define EIGEN_USE_GPU
- * #include <unsupported/Eigen/GPU>
- *
- * // CPU path (unchanged)
- * Eigen::LLT<Eigen::MatrixXd> llt_cpu(A);
- *
- * // GPU path (explicit)
- * Eigen::gpu::LLT<double> llt_gpu(A);   // L stays on device
- * auto X = llt_gpu.solve(B);            // only B transferred per solve
- * \endcode
- *
- * Requires CUDA 11.4+.
- */
-
-#ifdef EIGEN_USE_GPU
-// IWYU pragma: begin_exports
-#include "src/GPU/FwdDecl.h"
-#include "src/GPU/Meta.h"
-#include "src/GPU/type_traits.h"
-#include "src/GPU/DeviceScalar.h"
-#include "src/GPU/DeviceMatrix.h"
-#include "src/GPU/GpuContext.h"
-#include "src/GPU/DeviceExpr.h"
-#include "src/GPU/DeviceBlasExpr.h"
-#include "src/GPU/DeviceSolverExpr.h"
-#include "src/GPU/DeviceDispatch.h"
-#include "src/GPU/GpuSolverContext.h"
-#include "src/GPU/GpuLLT.h"
-#include "src/GPU/GpuLU.h"
-#include "src/GPU/GpuQR.h"
-#include "src/GPU/GpuSVD.h"
-#include "src/GPU/GpuEigenSolver.h"
-#include "src/GPU/CuFftSupport.h"
-#include "src/GPU/GpuFFT.h"
-#include "src/GPU/CuSparseSupport.h"
-#ifdef EIGEN_SPARSECORE_MODULE_H
-#include "src/GPU/GpuSparseContext.h"
-#endif
-#if defined(EIGEN_CUDSS) && defined(EIGEN_SPARSECORE_MODULE_H)
-#include "src/GPU/CuDssSupport.h"
-#include "src/GPU/GpuSparseSolverBase.h"
-#include "src/GPU/GpuSparseLLT.h"
-#include "src/GPU/GpuSparseLDLT.h"
-#include "src/GPU/GpuSparseLU.h"
-#endif
-// IWYU pragma: end_exports
-#endif
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_GPU_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_GPU_FORWARD_H
diff --git a/unsupported/Eigen/IterativeSolvers b/unsupported/Eigen/IterativeSolvers
index 41bfdfc..8998bbe 100644
--- a/unsupported/Eigen/IterativeSolvers
+++ b/unsupported/Eigen/IterativeSolvers
@@ -1,25 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/IterativeSolvers>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_ITERATIVE_SOLVERS_MODULE_H
-#define EIGEN_ITERATIVE_SOLVERS_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_ITERATIVESOLVERS_FORWARD_H
+#define EIGEN_UNSUPPORTED_ITERATIVESOLVERS_FORWARD_H
 
-// The contents of this module have been promoted to the supported
-// Eigen/IterativeLinearSolvers module. This header is retained as a thin
-// forwarding shim for backwards compatibility and may be removed in a future
-// release. Please include <Eigen/IterativeLinearSolvers> directly instead.
-#ifndef EIGEN_NO_DEPRECATED_WARNING
-#pragma message( \
-    "unsupported/Eigen/IterativeSolvers is deprecated and forwards to <Eigen/IterativeLinearSolvers>; please include that header directly. Define EIGEN_NO_DEPRECATED_WARNING to silence this message.")
-#endif
+#include "../../contrib/Eigen/IterativeSolvers"  // IWYU pragma: export
 
-#include "../../Eigen/IterativeLinearSolvers"
-
-#endif  // EIGEN_ITERATIVE_SOLVERS_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_ITERATIVESOLVERS_FORWARD_H
diff --git a/unsupported/Eigen/KroneckerProduct b/unsupported/Eigen/KroneckerProduct
index 40d0b1b..847612d 100644
--- a/unsupported/Eigen/KroneckerProduct
+++ b/unsupported/Eigen/KroneckerProduct
@@ -1,39 +1,17 @@
 // 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/KroneckerProduct>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_KRONECKER_PRODUCT_MODULE_H
-#define EIGEN_KRONECKER_PRODUCT_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_KRONECKERPRODUCT_FORWARD_H
+#define EIGEN_UNSUPPORTED_KRONECKERPRODUCT_FORWARD_H
 
-#include "../../Eigen/Core"
-#include "../../Eigen/SparseCore"
+#include "../../contrib/Eigen/KroneckerProduct"  // IWYU pragma: export
 
-namespace Eigen {
-
-/**
- * \defgroup KroneckerProduct_Module KroneckerProduct module
- *
- * This module contains an experimental Kronecker product implementation.
- *
- * \code
- * #include <unsupported/Eigen/KroneckerProduct>
- * \endcode
- */
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/KroneckerProduct/KroneckerTensorProduct.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_KRONECKER_PRODUCT_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_KRONECKERPRODUCT_FORWARD_H
diff --git a/unsupported/Eigen/LevenbergMarquardt b/unsupported/Eigen/LevenbergMarquardt
index eba68a7..e0991c2 100644
--- a/unsupported/Eigen/LevenbergMarquardt
+++ b/unsupported/Eigen/LevenbergMarquardt
@@ -1,46 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/LevenbergMarquardt>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_LEVENBERGMARQUARDT_MODULE_H
-#define EIGEN_LEVENBERGMARQUARDT_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_LEVENBERGMARQUARDT_FORWARD_H
+#define EIGEN_UNSUPPORTED_LEVENBERGMARQUARDT_FORWARD_H
 
-#include "../../Eigen/Core"
-#include "../../Eigen/Jacobi"
-#include "../../Eigen/QR"
-#include "../../Eigen/SparseCore"
-#include "../../Eigen/SparseQR"
-#include "NumericalDiff"
+#include "../../contrib/Eigen/LevenbergMarquardt"  // IWYU pragma: export
 
-/**
- * \defgroup LevenbergMarquardt_Module Levenberg-Marquardt module
- *
- * \code
- * #include <unsupported/Eigen/LevenbergMarquardt>
- * \endcode
- *
- *
- */
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-#include "src/LevenbergMarquardt/LMqrsolv.h"
-#include "src/LevenbergMarquardt/LMcovar.h"
-#include "src/LevenbergMarquardt/LMpar.h"
-#endif
-
-#include "src/LevenbergMarquardt/LevenbergMarquardt.h"
-#include "src/LevenbergMarquardt/LMonestep.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_LEVENBERGMARQUARDT_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_LEVENBERGMARQUARDT_FORWARD_H
diff --git a/unsupported/Eigen/MPRealSupport b/unsupported/Eigen/MPRealSupport
index 661143a..526c007 100644
--- a/unsupported/Eigen/MPRealSupport
+++ b/unsupported/Eigen/MPRealSupport
@@ -1,219 +1,17 @@
-// This file is part of a joint effort between Eigen, a lightweight C++ template library
-// for linear algebra, and MPFR C++, a C++ interface to MPFR library (http://www.holoborodko.com/pavel/)
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
 //
-// Copyright (C) 2010-2012 Pavel Holoborodko <pavel@holoborodko.com>
-// Copyright (C) 2010 Konstantin Holoborodko <konstantin@holoborodko.com>
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/MPRealSupport>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_MPREALSUPPORT_MODULE_H
-#define EIGEN_MPREALSUPPORT_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_MPREALSUPPORT_FORWARD_H
+#define EIGEN_UNSUPPORTED_MPREALSUPPORT_FORWARD_H
 
-#include "../../Eigen/Core"
-#include <mpreal.h>
+#include "../../contrib/Eigen/MPRealSupport"  // IWYU pragma: export
 
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/**
-  * \defgroup MPRealSupport_Module MPFRC++ Support module
-  * \code
-  * #include <unsupported/Eigen/MPRealSupport>
-  * \endcode
-  *
-  * This module provides support for multi precision floating point numbers
-  * via the <a href="http://www.holoborodko.com/pavel/mpfr">MPFR C++</a>
-  * library which itself is built upon <a href="http://www.mpfr.org/">MPFR</a>/<a href="http://gmplib.org/">GMP</a>.
-  *
-  * \warning MPFR C++ is licensed under the GPL.
-  *
-  * You can find a copy of MPFR C++ that is known to be compatible in the unsupported/test/mpreal folder.
-  *
-  * Here is an example:
-  *
-\code
-#include <iostream>
-#include <unsupported/Eigen/MPRealSupport>
-#include <Eigen/LU>
-using namespace mpfr;
-using namespace Eigen;
-int main()
-{
-  // set precision to 256 bits (double has only 53 bits)
-  mpreal::set_default_prec(256);
-  // Declare matrix and vector types with multi-precision scalar type
-  typedef Matrix<mpreal,Dynamic,Dynamic>  MatrixXmp;
-  typedef Matrix<mpreal,Dynamic,1>        VectorXmp;
-
-  MatrixXmp A = MatrixXmp::Random(100,100);
-  VectorXmp b = VectorXmp::Random(100);
-
-  // Solve Ax=b using LU
-  VectorXmp x = A.lu().solve(b);
-  std::cout << "relative error: " << (A*x - b).norm() / b.norm() << std::endl;
-  return 0;
-}
-\endcode
-  *
-  */
-
-template <>
-struct NumTraits<mpfr::mpreal> : GenericNumTraits<mpfr::mpreal> {
-  enum {
-    IsInteger = 0,
-    IsSigned = 1,
-    IsComplex = 0,
-    RequireInitialization = 1,
-    ReadCost = HugeCost,
-    AddCost = HugeCost,
-    MulCost = HugeCost
-  };
-
-  typedef mpfr::mpreal Real;
-  typedef mpfr::mpreal NonInteger;
-
-  static inline Real highest(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::maxval(Precision); }
-  static inline Real lowest(long Precision = mpfr::mpreal::get_default_prec()) { return -mpfr::maxval(Precision); }
-
-  // Constants
-  static inline Real Pi(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_pi(Precision); }
-  static inline Real Euler(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_euler(Precision); }
-  static inline Real Log2(long Precision = mpfr::mpreal::get_default_prec()) { return mpfr::const_log2(Precision); }
-  static inline Real Catalan(long Precision = mpfr::mpreal::get_default_prec()) {
-    return mpfr::const_catalan(Precision);
-  }
-
-  static inline Real epsilon(long Precision = mpfr::mpreal::get_default_prec()) {
-    return mpfr::machine_epsilon(Precision);
-  }
-  static inline Real epsilon(const Real& x) { return mpfr::machine_epsilon(x); }
-
-#ifdef MPREAL_HAVE_DYNAMIC_STD_NUMERIC_LIMITS
-  static inline int digits10(long Precision = mpfr::mpreal::get_default_prec()) {
-    return std::numeric_limits<Real>::digits10(Precision);
-  }
-  static inline int digits10(const Real& x) { return std::numeric_limits<Real>::digits10(x); }
-
-  static inline int max_digits10(long Precision = mpfr::mpreal::get_default_prec()) {
-    return std::numeric_limits<Real>::max_digits10(Precision);
-  }
-
-  static inline int digits() { return std::numeric_limits<Real>::digits(); }
-  static inline int digits(const Real& x) { return std::numeric_limits<Real>::digits(x); }
-#endif
-
-  static inline Real dummy_precision() {
-    mpfr_prec_t weak_prec = ((mpfr::mpreal::get_default_prec() - 1) * 90) / 100;
-    return mpfr::machine_epsilon(weak_prec);
-  }
-};
-
-namespace internal {
-
-template <>
-inline mpfr::mpreal random<mpfr::mpreal>() {
-  return mpfr::random();
-}
-
-template <>
-inline mpfr::mpreal random<mpfr::mpreal>(const mpfr::mpreal& a, const mpfr::mpreal& b) {
-  return a + (b - a) * random<mpfr::mpreal>();
-}
-
-inline bool isMuchSmallerThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps) {
-  return mpfr::abs(a) <= mpfr::abs(b) * eps;
-}
-
-inline bool isApprox(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps) {
-  return mpfr::isEqualFuzzy(a, b, eps);
-}
-
-inline bool isApproxOrLessThan(const mpfr::mpreal& a, const mpfr::mpreal& b, const mpfr::mpreal& eps) {
-  return a <= b || mpfr::isEqualFuzzy(a, b, eps);
-}
-
-template <>
-inline long double cast<mpfr::mpreal, long double>(const mpfr::mpreal& x) {
-  return x.toLDouble();
-}
-
-template <>
-inline double cast<mpfr::mpreal, double>(const mpfr::mpreal& x) {
-  return x.toDouble();
-}
-
-template <>
-inline long cast<mpfr::mpreal, long>(const mpfr::mpreal& x) {
-  return x.toLong();
-}
-
-template <>
-inline int cast<mpfr::mpreal, int>(const mpfr::mpreal& x) {
-  return int(x.toLong());
-}
-
-// Specialize GEBP kernel and traits for mpreal (no need for peeling, nor complicated stuff)
-// This also permits to directly call mpfr's routines and avoid many temporaries produced by mpreal
-template <>
-class gebp_traits<mpfr::mpreal, mpfr::mpreal, false, false> {
- public:
-  typedef mpfr::mpreal ResScalar;
-  enum {
-    Vectorizable = false,
-    LhsPacketSize = 1,
-    RhsPacketSize = 1,
-    ResPacketSize = 1,
-    NumberOfRegisters = 1,
-    nr = 1,
-    mr = 1,
-    LhsProgress = 1,
-    RhsProgress = 1
-  };
-  typedef ResScalar LhsPacket;
-  typedef ResScalar RhsPacket;
-  typedef ResScalar ResPacket;
-  typedef LhsPacket LhsPacket4Packing;
-};
-
-template <typename Index, typename DataMapper, bool ConjugateLhs, bool ConjugateRhs>
-struct gebp_kernel<mpfr::mpreal, mpfr::mpreal, Index, DataMapper, 1, 1, ConjugateLhs, ConjugateRhs> {
-  typedef mpfr::mpreal mpreal;
-
-  EIGEN_DONT_INLINE void operator()(const DataMapper& res, const mpreal* blockA, const mpreal* blockB, Index rows,
-                                    Index depth, Index cols, const mpreal& alpha, Index strideA = -1,
-                                    Index strideB = -1, Index offsetA = 0, Index offsetB = 0) {
-    if (rows == 0 || cols == 0 || depth == 0) return;
-
-    mpreal acc1(0, mpfr_get_prec(blockA[0].mpfr_srcptr())), tmp(0, mpfr_get_prec(blockA[0].mpfr_srcptr()));
-
-    if (strideA == -1) strideA = depth;
-    if (strideB == -1) strideB = depth;
-
-    for (Index i = 0; i < rows; ++i) {
-      for (Index j = 0; j < cols; ++j) {
-        const mpreal* A = blockA + i * strideA + offsetA;
-        const mpreal* B = blockB + j * strideB + offsetB;
-
-        acc1 = 0;
-        for (Index k = 0; k < depth; k++) {
-          mpfr_mul(tmp.mpfr_ptr(), A[k].mpfr_srcptr(), B[k].mpfr_srcptr(), mpreal::get_default_rnd());
-          mpfr_add(acc1.mpfr_ptr(), acc1.mpfr_ptr(), tmp.mpfr_ptr(), mpreal::get_default_rnd());
-        }
-
-        mpfr_mul(acc1.mpfr_ptr(), acc1.mpfr_srcptr(), alpha.mpfr_srcptr(), mpreal::get_default_rnd());
-        mpfr_add(res(i, j).mpfr_ptr(), res(i, j).mpfr_srcptr(), acc1.mpfr_srcptr(), mpreal::get_default_rnd());
-      }
-    }
-  }
-};
-}  // end namespace internal
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_MPREALSUPPORT_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_MPREALSUPPORT_FORWARD_H
diff --git a/unsupported/Eigen/MatrixFunctions b/unsupported/Eigen/MatrixFunctions
index aa2137e..b097a1f 100644
--- a/unsupported/Eigen/MatrixFunctions
+++ b/unsupported/Eigen/MatrixFunctions
@@ -1,505 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Jitse Niesen <jitse@maths.leeds.ac.uk>
-// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/MatrixFunctions>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_MATRIX_FUNCTIONS_MODULE_H
-#define EIGEN_MATRIX_FUNCTIONS_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_MATRIXFUNCTIONS_FORWARD_H
+#define EIGEN_UNSUPPORTED_MATRIXFUNCTIONS_FORWARD_H
 
-#include <cfloat>
-#include <list>
+#include "../../contrib/Eigen/MatrixFunctions"  // IWYU pragma: export
 
-#include "../../Eigen/Core"
-#include "../../Eigen/LU"
-#include "../../Eigen/Eigenvalues"
-
-/**
- * \defgroup MatrixFunctions_Module Matrix functions module
- * \brief This module aims to provide various methods for the computation of
- * matrix functions.
- *
- * To use this module, add
- * \code
- * #include <unsupported/Eigen/MatrixFunctions>
- * \endcode
- * at the start of your source file.
- *
- * This module defines the following MatrixBase methods.
- *  - \ref matrixbase_cos "MatrixBase::cos()", for computing the matrix cosine
- *  - \ref matrixbase_cosh "MatrixBase::cosh()", for computing the matrix hyperbolic cosine
- *  - \ref matrixbase_exp "MatrixBase::exp()", for computing the matrix exponential
- *  - \ref matrixbase_log "MatrixBase::log()", for computing the matrix logarithm
- *  - \ref matrixbase_pow "MatrixBase::pow()", for computing the matrix power
- *  - \ref matrixbase_matrixfunction "MatrixBase::matrixFunction()", for computing general matrix functions
- *  - \ref matrixbase_sin "MatrixBase::sin()", for computing the matrix sine
- *  - \ref matrixbase_sinh "MatrixBase::sinh()", for computing the matrix hyperbolic sine
- *  - \ref matrixbase_sqrt "MatrixBase::sqrt()", for computing the matrix square root
- *
- * These methods are the main entry points to this module.
- *
- * %Matrix functions are defined as follows.  Suppose that \f$ f \f$
- * is an entire function (that is, a function on the complex plane
- * that is everywhere complex differentiable).  Then its Taylor
- * series
- * \f[ f(0) + f'(0) x + \frac{f''(0)}{2} x^2 + \frac{f'''(0)}{3!} x^3 + \cdots \f]
- * converges to \f$ f(x) \f$. In this case, we can define the matrix
- * function by the same series:
- * \f[ f(M) = f(0) + f'(0) M + \frac{f''(0)}{2} M^2 + \frac{f'''(0)}{3!} M^3 + \cdots \f]
- *
- */
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/MatrixFunctions/MatrixExponential.h"
-#include "src/MatrixFunctions/MatrixFunction.h"
-#include "src/MatrixFunctions/MatrixSquareRoot.h"
-#include "src/MatrixFunctions/MatrixLogarithm.h"
-#include "src/MatrixFunctions/MatrixPower.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-/**
-\page matrixbaseextra_page
-\ingroup MatrixFunctions_Module
-
-\section matrixbaseextra MatrixBase methods defined in the MatrixFunctions module
-
-The remainder of the page documents the following MatrixBase methods
-which are defined in the MatrixFunctions module.
-
-
-
-\subsection matrixbase_cos MatrixBase::cos()
-
-Compute the matrix cosine.
-
-\code
-const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cos() const
-\endcode
-
-\param[in]  M  a square matrix.
-\returns  expression representing \f$ \cos(M) \f$.
-
-This function computes the matrix cosine. Use ArrayBase::cos() for computing the entry-wise cosine.
-
-The implementation calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cos().
-
-\sa \ref matrixbase_sin "sin()" for an example.
-
-
-
-\subsection matrixbase_cosh MatrixBase::cosh()
-
-Compute the matrix hyberbolic cosine.
-
-\code
-const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cosh() const
-\endcode
-
-\param[in]  M  a square matrix.
-\returns  expression representing \f$ \cosh(M) \f$
-
-This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cosh().
-
-\sa \ref matrixbase_sinh "sinh()" for an example.
-
-
-
-\subsection matrixbase_exp MatrixBase::exp()
-
-Compute the matrix exponential.
-
-\code
-const MatrixExponentialReturnValue<Derived> MatrixBase<Derived>::exp() const
-\endcode
-
-\param[in]  M  matrix whose exponential is to be computed.
-\returns    expression representing the matrix exponential of \p M.
-
-The matrix exponential of \f$ M \f$ is defined by
-\f[ \exp(M) = \sum_{k=0}^\infty \frac{M^k}{k!}. \f]
-The matrix exponential can be used to solve linear ordinary
-differential equations: the solution of \f$ y' = My \f$ with the
-initial condition \f$ y(0) = y_0 \f$ is given by
-\f$ y(t) = \exp(M) y_0 \f$.
-
-The matrix exponential is different from applying the exp function to all the entries in the matrix.
-Use ArrayBase::exp() if you want to do the latter.
-
-The cost of the computation is approximately \f$ 20 n^3 \f$ for
-matrices of size \f$ n \f$. The number 20 depends weakly on the
-norm of the matrix.
-
-The matrix exponential is computed using the scaling-and-squaring
-method combined with Pad&eacute; approximation. The matrix is first
-rescaled, then the exponential of the reduced matrix is computed
-approximant, and then the rescaling is undone by repeated
-squaring. The degree of the Pad&eacute; approximant is chosen such
-that the approximation error is less than the round-off
-error. However, errors may accumulate during the squaring phase.
-
-Details of the algorithm can be found in: Nicholas J. Higham, "The
-scaling and squaring method for the matrix exponential revisited,"
-<em>SIAM J. %Matrix Anal. Applic.</em>, <b>26</b>:1179&ndash;1193,
-2005.
-
-Example: The following program checks that
-\f[ \exp \left[ \begin{array}{ccc}
-      0 & \frac14\pi & 0 \\
-      -\frac14\pi & 0 & 0 \\
-      0 & 0 & 0
-    \end{array} \right] = \left[ \begin{array}{ccc}
-      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
-      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
-      0 & 0 & 1
-    \end{array} \right]. \f]
-This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
-the z-axis.
-
-\include MatrixExponential.cpp
-Output: \verbinclude MatrixExponential.out
-
-\note \p M has to be a matrix of \c float, \c double, `long double`
-\c complex<float>, \c complex<double>, or `complex<long double>` .
-
-
-\subsection matrixbase_log MatrixBase::log()
-
-Compute the matrix logarithm.
-
-\code
-const MatrixLogarithmReturnValue<Derived> MatrixBase<Derived>::log() const
-\endcode
-
-\param[in]  M  invertible matrix whose logarithm is to be computed.
-\returns    expression representing the matrix logarithm root of \p M.
-
-The matrix logarithm of \f$ M \f$ is a matrix \f$ X \f$ such that
-\f$ \exp(X) = M \f$ where exp denotes the matrix exponential. As for
-the scalar logarithm, the equation \f$ \exp(X) = M \f$ may have
-multiple solutions; this function returns a matrix whose eigenvalues
-have imaginary part in the interval \f$ (-\pi,\pi] \f$.
-
-The matrix logarithm is different from applying the log function to all the entries in the matrix.
-Use ArrayBase::log() if you want to do the latter.
-
-In the real case, the matrix \f$ M \f$ should be invertible and
-it should have no eigenvalues which are real and negative (pairs of
-complex conjugate eigenvalues are allowed). In the complex case, it
-only needs to be invertible.
-
-This function computes the matrix logarithm using the Schur-Parlett
-algorithm as implemented by MatrixBase::matrixFunction(). The
-logarithm of an atomic block is computed by MatrixLogarithmAtomic,
-which uses direct computation for 1-by-1 and 2-by-2 blocks and an
-inverse scaling-and-squaring algorithm for bigger blocks, with the
-square roots computed by MatrixBase::sqrt().
-
-Details of the algorithm can be found in Section 11.6.2 of:
-Nicholas J. Higham,
-<em>Functions of Matrices: Theory and Computation</em>,
-SIAM 2008. ISBN 978-0-898716-46-7.
-
-Example: The following program checks that
-\f[ \log \left[ \begin{array}{ccc}
-      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
-      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
-      0 & 0 & 1
-    \end{array} \right] = \left[ \begin{array}{ccc}
-      0 & \frac14\pi & 0 \\
-      -\frac14\pi & 0 & 0 \\
-      0 & 0 & 0
-    \end{array} \right]. \f]
-This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
-the z-axis. This is the inverse of the example used in the
-documentation of \ref matrixbase_exp "exp()".
-
-\include MatrixLogarithm.cpp
-Output: \verbinclude MatrixLogarithm.out
-
-\note \p M has to be a matrix of \c float, \c double, `long
-double`, \c complex<float>, \c complex<double>, or `complex<long double>`.
-
-\sa MatrixBase::exp(), MatrixBase::matrixFunction(),
-    class MatrixLogarithmAtomic, MatrixBase::sqrt().
-
-
-\subsection matrixbase_pow MatrixBase::pow()
-
-Compute the matrix raised to arbitrary real power.
-
-\code
-const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(RealScalar p) const
-\endcode
-
-\param[in]  M  base of the matrix power, should be a square matrix.
-\param[in]  p  exponent of the matrix power.
-
-The matrix power \f$ M^p \f$ is defined as \f$ \exp(p \log(M)) \f$,
-where exp denotes the matrix exponential, and log denotes the matrix
-logarithm. This is different from raising all the entries in the matrix
-to the p-th power. Use ArrayBase::pow() if you want to do the latter.
-
-If \p p is complex, the scalar type of \p M should be the type of \p
-p . \f$ M^p \f$ simply evaluates into \f$ \exp(p \log(M)) \f$.
-Therefore, the matrix \f$ M \f$ should meet the conditions to be an
-argument of matrix logarithm.
-
-If \p p is real, it is casted into the real scalar type of \p M. Then
-this function computes the matrix power using the Schur-Pad&eacute;
-algorithm as implemented by class MatrixPower. The exponent is split
-into integral part and fractional part, where the fractional part is
-in the interval \f$ (-1, 1) \f$. The main diagonal and the first
-super-diagonal is directly computed.
-
-If \p M is singular with a semisimple zero eigenvalue and \p p is
-positive, the Schur factor \f$ T \f$ is reordered with Givens
-rotations, i.e.
-
-\f[ T = \left[ \begin{array}{cc}
-      T_1 & T_2 \\
-      0   & 0
-    \end{array} \right] \f]
-
-where \f$ T_1 \f$ is invertible. Then \f$ T^p \f$ is given by
-
-\f[ T^p = \left[ \begin{array}{cc}
-      T_1^p & T_1^{-1} T_1^p T_2 \\
-      0     & 0
-    \end{array}. \right] \f]
-
-\warning Fractional power of a matrix with a non-semisimple zero
-eigenvalue is not well-defined. We introduce an assertion failure
-against inaccurate result, e.g. \code
-#include <unsupported/Eigen/MatrixFunctions>
-#include <iostream>
-
-int main()
-{
-  Eigen::Matrix4d A;
-  A << 0, 0, 2, 3,
-       0, 0, 4, 5,
-       0, 0, 6, 7,
-       0, 0, 8, 9;
-  std::cout << A.pow(0.37) << std::endl;
-
-  // The 1 makes eigenvalue 0 non-semisimple.
-  A.coeffRef(0, 1) = 1;
-
-  // This fails if EIGEN_NO_DEBUG is undefined.
-  std::cout << A.pow(0.37) << std::endl;
-
-  return 0;
-}
-\endcode
-
-Details of the algorithm can be found in: Nicholas J. Higham and
-Lijing Lin, "A Schur-Pad&eacute; algorithm for fractional powers of a
-matrix," <em>SIAM J. %Matrix Anal. Applic.</em>,
-<b>32(3)</b>:1056&ndash;1078, 2011.
-
-Example: The following program checks that
-\f[ \left[ \begin{array}{ccc}
-      \cos1 & -\sin1 & 0 \\
-      \sin1 & \cos1 & 0 \\
-      0 & 0 & 1
-    \end{array} \right]^{\frac14\pi} = \left[ \begin{array}{ccc}
-      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
-      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
-      0 & 0 & 1
-    \end{array} \right]. \f]
-This corresponds to \f$ \frac14\pi \f$ rotations of 1 radian around
-the z-axis.
-
-\include MatrixPower.cpp
-Output: \verbinclude MatrixPower.out
-
-MatrixBase::pow() is user-friendly. However, there are some
-circumstances under which you should use class MatrixPower directly.
-MatrixPower can save the result of Schur decomposition, so it's
-better for computing various powers for the same matrix.
-
-Example:
-\include MatrixPower_optimal.cpp
-Output: \verbinclude MatrixPower_optimal.out
-
-\note \p M has to be a matrix of \c float, \c double, `long
-double`, \c complex<float>, \c complex<double>, or
-\c complex<long double> .
-
-\sa MatrixBase::exp(), MatrixBase::log(), class MatrixPower.
-
-
-\subsection matrixbase_matrixfunction MatrixBase::matrixFunction()
-
-Compute a matrix function.
-
-\code
-const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::matrixFunction(typename internal::stem_function<typename
-internal::traits<Derived>::Scalar>::type f) const \endcode
-
-\param[in]  M  argument of matrix function, should be a square matrix.
-\param[in]  f  an entire function; \c f(x,n) should compute the n-th
-derivative of f at x.
-\returns  expression representing \p f applied to \p M.
-
-Suppose that \p M is a matrix whose entries have type \c Scalar.
-Then, the second argument, \p f, should be a function with prototype
-\code
-ComplexScalar f(ComplexScalar, int)
-\endcode
-where \c ComplexScalar = \c std::complex<Scalar> if \c Scalar is
-real (e.g., \c float or \c double) and \c ComplexScalar =
-\c Scalar if \c Scalar is complex. The return value of \c f(x,n)
-should be \f$ f^{(n)}(x) \f$, the n-th derivative of f at x.
-
-This routine uses the algorithm described in:
-Philip Davies and Nicholas J. Higham,
-"A Schur-Parlett algorithm for computing matrix functions",
-<em>SIAM J. %Matrix Anal. Applic.</em>, <b>25</b>:464&ndash;485, 2003.
-
-The actual work is done by the MatrixFunction class.
-
-Example: The following program checks that
-\f[ \exp \left[ \begin{array}{ccc}
-      0 & \frac14\pi & 0 \\
-      -\frac14\pi & 0 & 0 \\
-      0 & 0 & 0
-    \end{array} \right] = \left[ \begin{array}{ccc}
-      \frac12\sqrt2 & -\frac12\sqrt2 & 0 \\
-      \frac12\sqrt2 & \frac12\sqrt2 & 0 \\
-      0 & 0 & 1
-    \end{array} \right]. \f]
-This corresponds to a rotation of \f$ \frac14\pi \f$ radians around
-the z-axis. This is the same example as used in the documentation
-of \ref matrixbase_exp "exp()".
-
-\include MatrixFunction.cpp
-Output: \verbinclude MatrixFunction.out
-
-Note that the function \c expfn is defined for complex numbers
-\c x, even though the matrix \c A is over the reals. Instead of
-\c expfn, we could also have used StdStemFunctions::exp:
-\code
-A.matrixFunction(StdStemFunctions<std::complex<double> >::exp, &B);
-\endcode
-
-
-
-\subsection matrixbase_sin MatrixBase::sin()
-
-Compute the matrix sine.
-
-\code
-const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sin() const
-\endcode
-
-\param[in]  M  a square matrix.
-\returns  expression representing \f$ \sin(M) \f$.
-
-This function computes the matrix sine. Use ArrayBase::sin() for computing the entry-wise sine.
-
-The implementation calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sin().
-
-Example: \include MatrixSine.cpp
-Output: \verbinclude MatrixSine.out
-
-
-
-\subsection matrixbase_sinh MatrixBase::sinh()
-
-Compute the matrix hyperbolic sine.
-
-\code
-MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sinh() const
-\endcode
-
-\param[in]  M  a square matrix.
-\returns  expression representing \f$ \sinh(M) \f$
-
-This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sinh().
-
-Example: \include MatrixSinh.cpp
-Output: \verbinclude MatrixSinh.out
-
-
-\subsection matrixbase_sqrt MatrixBase::sqrt()
-
-Compute the matrix square root.
-
-\code
-const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const
-\endcode
-
-\param[in]  M  invertible matrix whose square root is to be computed.
-\returns    expression representing the matrix square root of \p M.
-
-The matrix square root of \f$ M \f$ is the matrix \f$ M^{1/2} \f$
-whose square is the original matrix; so if \f$ S = M^{1/2} \f$ then
-\f$ S^2 = M \f$. This is different from taking the square root of all
-the entries in the matrix; use ArrayBase::sqrt() if you want to do the
-latter.
-
-In the <b>real case</b>, the matrix \f$ M \f$ should be invertible and
-it should have no eigenvalues which are real and negative (pairs of
-complex conjugate eigenvalues are allowed). In that case, the matrix
-has a square root which is also real, and this is the square root
-computed by this function.
-
-The matrix square root is computed by first reducing the matrix to
-quasi-triangular form with the real Schur decomposition. The square
-root of the quasi-triangular matrix can then be computed directly. The
-cost is approximately \f$ 25 n^3 \f$ real flops for the real Schur
-decomposition and \f$ 3\frac13 n^3 \f$ real flops for the remainder
-(though the computation time in practice is likely more than this
-indicates).
-
-Details of the algorithm can be found in: Nicholas J. Highan,
-"Computing real square roots of a real matrix", <em>Linear Algebra
-Appl.</em>, 88/89:405&ndash;430, 1987.
-
-If the matrix is <b>positive-definite symmetric</b>, then the square
-root is also positive-definite symmetric. In this case, it is best to
-use SelfAdjointEigenSolver::operatorSqrt() to compute it.
-
-In the <b>complex case</b>, the matrix \f$ M \f$ should be invertible;
-this is a restriction of the algorithm. The square root computed by
-this algorithm is the one whose eigenvalues have an argument in the
-interval \f$ (-\frac12\pi, \frac12\pi] \f$. This is the usual branch
-cut.
-
-The computation is the same as in the real case, except that the
-complex Schur decomposition is used to reduce the matrix to a
-triangular matrix. The theoretical cost is the same. Details are in:
-&Aring;ke Bj&ouml;rck and Sven Hammarling, "A Schur method for the
-square root of a matrix", <em>Linear Algebra Appl.</em>,
-52/53:127&ndash;140, 1983.
-
-Example: The following program checks that the square root of
-\f[ \left[ \begin{array}{cc}
-              \cos(\frac13\pi) & -\sin(\frac13\pi) \\
-              \sin(\frac13\pi) & \cos(\frac13\pi)
-    \end{array} \right], \f]
-corresponding to a rotation over 60 degrees, is a rotation over 30 degrees:
-\f[ \left[ \begin{array}{cc}
-              \cos(\frac16\pi) & -\sin(\frac16\pi) \\
-              \sin(\frac16\pi) & \cos(\frac16\pi)
-    \end{array} \right]. \f]
-
-\include MatrixSquareRoot.cpp
-Output: \verbinclude MatrixSquareRoot.out
-
-\sa class RealSchur, class ComplexSchur, class MatrixSquareRoot,
-    SelfAdjointEigenSolver::operatorSqrt().
-
-*/
-
-#endif  // EIGEN_MATRIX_FUNCTIONS_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_MATRIXFUNCTIONS_FORWARD_H
diff --git a/unsupported/Eigen/NNLS b/unsupported/Eigen/NNLS
index d1c9cfb..04ff1a9 100644
--- a/unsupported/Eigen/NNLS
+++ b/unsupported/Eigen/NNLS
@@ -1,416 +1,17 @@
-/* Non-Negagive Least Squares Algorithm for Eigen.
- *
- * Copyright (C) 2021 Essex Edwards, <essex.edwards@gmail.com>
- * Copyright (C) 2013 Hannes Matuschek, hannes.matuschek at uni-potsdam.de
- *
- * 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/.
- */
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/NNLS>
+// directly. This shim preserves the legacy include path.
 
-/** \defgroup nnls Non-Negative Least Squares (NNLS) Module
- * This module provides a single class @c Eigen::NNLS implementing the NNLS algorithm.
- * The algorithm is described in "SOLVING LEAST SQUARES PROBLEMS", by Charles L. Lawson and
- * Richard J. Hanson, Prentice-Hall, 1974 and solves optimization problems of the form
- *
- * \f[ \min \left\Vert Ax-b\right\Vert_2^2\quad s.t.\, x\ge 0\,.\f]
- *
- * The algorithm solves the constrained least-squares problem above by iteratively improving
- * an estimate of which constraints are active (elements of \f$x\f$ equal to zero)
- * and which constraints are inactive (elements of \f$x\f$ greater than zero).
- * Each iteration, an unconstrained linear least-squares problem solves for the
- * components of \f$x\f$ in the (estimated) inactive set and the sets are updated.
- * The unconstrained problem minimizes \f$\left\Vert A^Nx^N-b\right\Vert_2^2\f$,
- * where \f$A^N\f$ is a matrix formed by selecting all columns of A which are
- * in the inactive set \f$N\f$.
- *
- */
+#ifndef EIGEN_UNSUPPORTED_NNLS_FORWARD_H
+#define EIGEN_UNSUPPORTED_NNLS_FORWARD_H
 
-#ifndef EIGEN_NNLS_MODULE_H
-#define EIGEN_NNLS_MODULE_H
+#include "../../contrib/Eigen/NNLS"  // IWYU pragma: export
 
-#include "../../Eigen/Core"
-#include "../../Eigen/QR"
-
-#include <limits>
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/** \ingroup nnls
- * \class NNLS
- * \brief Implementation of the Non-Negative Least Squares (NNLS) algorithm.
- * \tparam MatrixType The type of the system matrix \f$A\f$.
- *
- * This class implements the NNLS algorithm as described in "SOLVING LEAST SQUARES PROBLEMS",
- * Charles L. Lawson and Richard J. Hanson, Prentice-Hall, 1974. This algorithm solves a least
- * squares problem iteratively and ensures that the solution is non-negative. I.e.
- *
- * \f[ \min \left\Vert Ax-b\right\Vert_2^2\quad s.t.\, x\ge 0 \f]
- *
- * The algorithm solves the constrained least-squares problem above by iteratively improving
- * an estimate of which constraints are active (elements of \f$x\f$ equal to zero)
- * and which constraints are inactive (elements of \f$x\f$ greater than zero).
- * Each iteration, an unconstrained linear least-squares problem solves for the
- * components of \f$x\f$ in the (estimated) inactive set and the sets are updated.
- * The unconstrained problem minimizes \f$\left\Vert A^Nx^N-b\right\Vert_2^2\f$,
- * where \f$A^N\f$ is a matrix formed by selecting all columns of A which are
- * in the inactive set \f$N\f$.
- *
- * See <a href="https://en.wikipedia.org/wiki/Non-negative_least_squares">the
- * wikipedia page on non-negative least squares</a> for more background information.
- *
- * \note Please note that it is possible to construct an NNLS problem for which the
- *       algorithm does not converge. In practice these cases are extremely rare.
- */
-template <class MatrixType_>
-class NNLS {
- public:
-  typedef MatrixType_ MatrixType;
-
-  enum {
-    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
-    ColsAtCompileTime = MatrixType::ColsAtCompileTime,
-    Options = MatrixType::Options,
-    MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
-    MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
-  };
-
-  typedef typename MatrixType::Scalar Scalar;
-  typedef typename MatrixType::RealScalar RealScalar;
-  typedef typename MatrixType::Index Index;
-
-  /** Type of a row vector of the system matrix \f$A\f$. */
-  typedef Matrix<Scalar, ColsAtCompileTime, 1> SolutionVectorType;
-  /** Type of a column vector of the system matrix \f$A\f$. */
-  typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsVectorType;
-  typedef Matrix<Index, ColsAtCompileTime, 1> IndicesType;
-
-  /** */
-  NNLS();
-
-  /** \brief Constructs a NNLS solver and initializes it with the given system matrix @c A.
-   * \param A Specifies the system matrix.
-   * \param max_iter Specifies the maximum number of iterations to solve the system.
-   * \param tol Specifies the precision of the optimum.
-   *        This is an absolute tolerance on the gradient of the Lagrangian, \f$A^T(Ax-b)-\lambda\f$
-   *        (with Lagrange multipliers \f$\lambda\f$).
-   */
-  NNLS(const MatrixType &A, Index max_iter = -1, Scalar tol = NumTraits<Scalar>::dummy_precision());
-
-  /** Initializes the solver with the matrix \a A for further solving NNLS problems.
-   *
-   * This function mostly initializes/computes the preconditioner. In the future
-   * we might, for instance, implement column reordering for faster matrix vector products.
-   */
-  template <typename MatrixDerived>
-  NNLS<MatrixType> &compute(const EigenBase<MatrixDerived> &A);
-
-  /** \brief Solves the NNLS problem.
-   *
-   * The dimension of @c b must be equal to the number of rows of @c A, given to the constructor.
-   *
-   * \returns The approximate solution vector \f$ x \f$. Use info() to determine if the solve was a success or not.
-   * \sa info()
-   */
-  const SolutionVectorType &solve(const RhsVectorType &b);
-
-  /** \brief Returns the solution if a problem was solved.
-   * If not, an uninitialized vector may be returned. */
-  const SolutionVectorType &x() const { return x_; }
-
-  /** \returns the tolerance threshold used by the stopping criteria.
-   * \sa setTolerance()
-   */
-  Scalar tolerance() const { return tolerance_; }
-
-  /** Sets the tolerance threshold used by the stopping criteria.
-   *
-   * This is an absolute tolerance on the gradient of the Lagrangian, \f$A^T(Ax-b)-\lambda\f$
-   * (with Lagrange multipliers \f$\lambda\f$).
-   */
-  NNLS<MatrixType> &setTolerance(const Scalar &tolerance) {
-    tolerance_ = tolerance;
-    return *this;
-  }
-
-  /** \returns the max number of iterations.
-   * It is either the value set by setMaxIterations or, by default, twice the number of columns of the matrix.
-   */
-  Index maxIterations() const { return max_iter_ < 0 ? 2 * A_.cols() : max_iter_; }
-
-  /** Sets the max number of iterations.
-   * Default is twice the number of columns of the matrix.
-   * The algorithm requires at least k iterations to produce a solution vector with k non-zero entries.
-   */
-  NNLS<MatrixType> &setMaxIterations(Index maxIters) {
-    max_iter_ = maxIters;
-    return *this;
-  }
-
-  /** \returns the number of iterations (least-squares solves) performed during the last solve */
-  Index iterations() const { return iterations_; }
-
-  /** \returns Success if the iterations converged, and an error values otherwise. */
-  ComputationInfo info() const { return info_; }
-
- private:
-  /** \internal Adds the given index @c idx to the inactive set N and updates the QR decomposition of \f$A^N\f$. */
-  void moveToInactiveSet_(Index idx);
-
-  /** \internal Removes the given index idx from the inactive set N and updates the QR decomposition of \f$A^N\f$. */
-  void moveToActiveSet_(Index idx);
-
-  /** \internal Solves the least-squares problem \f$\left\Vert y-A^Nx\right\Vert_2^2\f$. */
-  void solveInactiveSet_(const RhsVectorType &b);
-
- private:
-  typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixAtAType;
-
-  /** \internal Holds the maximum number of iterations for the NNLS algorithm.
-   *  @c -1 means to use the default value. */
-  Index max_iter_;
-  /** \internal Holds the number of iterations. */
-  Index iterations_;
-  /** \internal Holds success/fail of the last solve. */
-  ComputationInfo info_;
-  /** \internal Size of the inactive set. */
-  Index numInactive_;
-  /** \internal Accuracy of the algorithm w.r.t the optimality of the solution (gradient). */
-  Scalar tolerance_;
-  /** \internal The system matrix, a copy of the one given to the constructor. */
-  MatrixType A_;
-  /** \internal Precomputed product \f$A^TA\f$. */
-  MatrixAtAType AtA_;
-  /** \internal Will hold the solution. */
-  SolutionVectorType x_;
-  /** \internal Will hold the current gradient.\f$A^Tb - A^TAx\f$ */
-  SolutionVectorType gradient_;
-  /** \internal Will hold the partial solution. */
-  SolutionVectorType y_;
-  /** \internal Precomputed product \f$A^Tb\f$. */
-  SolutionVectorType Atb_;
-  /** \internal Holds the current permutation partitioning the active and inactive sets.
-   * The first @c numInactive_ elements form the inactive set and the rest the active set. */
-  IndicesType index_sets_;
-  /** \internal QR decomposition to solve the (inactive) sub system (together with @c qrCoeffs_). */
-  MatrixType QR_;
-  /** \internal QR decomposition to solve the (inactive) sub system (together with @c QR_). */
-  SolutionVectorType qrCoeffs_;
-  /** \internal Some workspace for QR decomposition. */
-  SolutionVectorType tempSolutionVector_;
-  RhsVectorType tempRhsVector_;
-};
-
-/* ********************************************************************************************
- * Implementation
- * ******************************************************************************************** */
-
-template <typename MatrixType>
-NNLS<MatrixType>::NNLS()
-    : max_iter_(-1),
-      iterations_(0),
-      info_(ComputationInfo::InvalidInput),
-      numInactive_(0),
-      tolerance_(NumTraits<Scalar>::dummy_precision()) {}
-
-template <typename MatrixType>
-NNLS<MatrixType>::NNLS(const MatrixType &A, Index max_iter, Scalar tol) : max_iter_(max_iter), tolerance_(tol) {
-  compute(A);
-}
-
-template <typename MatrixType>
-template <typename MatrixDerived>
-NNLS<MatrixType> &NNLS<MatrixType>::compute(const EigenBase<MatrixDerived> &A) {
-  // Ensure Scalar type is real. The non-negativity constraint doesn't obviously extend to complex numbers.
-  EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL);
-
-  // max_iter_: unchanged
-  iterations_ = 0;
-  info_ = ComputationInfo::Success;
-  numInactive_ = 0;
-  // tolerance: unchanged
-  A_ = A.derived();
-  AtA_.noalias() = A_.transpose() * A_;
-  x_.resize(A_.cols());
-  gradient_.resize(A_.cols());
-  y_.resize(A_.cols());
-  Atb_.resize(A_.cols());
-  index_sets_.resize(A_.cols());
-  QR_.resize(A_.rows(), A_.cols());
-  qrCoeffs_.resize(A_.cols());
-  tempSolutionVector_.resize(A_.cols());
-  tempRhsVector_.resize(A_.rows());
-
-  return *this;
-}
-
-template <typename MatrixType>
-const typename NNLS<MatrixType>::SolutionVectorType &NNLS<MatrixType>::solve(const RhsVectorType &b) {
-  // Initialize solver
-  iterations_ = 0;
-  info_ = ComputationInfo::NumericalIssue;
-  x_.setZero();
-
-  index_sets_ = IndicesType::LinSpaced(A_.cols(), 0, A_.cols() - 1);  // Identity permutation.
-  numInactive_ = 0;
-
-  // Precompute A^T*b
-  Atb_.noalias() = A_.transpose() * b;
-
-  if (A_.rows() == 0) {
-    info_ = ComputationInfo::Success;
-    return x_;
-  }
-
-  const Index maxIterations = this->maxIterations();
-
-  // OUTER LOOP
-  while (true) {
-    // Early exit if all variables are inactive, which breaks 'maxCoeff' below.
-    if (A_.cols() == numInactive_) {
-      info_ = ComputationInfo::Success;
-      return x_;
-    }
-
-    // Find the maximum element of the gradient in the active set.
-    // If it is small or negative, then we have converged.
-    // Else, we move that variable to the inactive set.
-    gradient_.noalias() = Atb_ - AtA_ * x_;
-    if (!gradient_.allFinite()) return x_;
-
-    const Index numActive = A_.cols() - numInactive_;
-    Index argmaxGradient = -1;
-    const Scalar maxGradient = gradient_(index_sets_.tail(numActive)).maxCoeff(&argmaxGradient);
-    argmaxGradient += numInactive_;  // because tail() skipped the first numInactive_ elements
-
-    if (maxGradient < tolerance_) {
-      info_ = ComputationInfo::Success;
-      return x_;
-    }
-
-    if (iterations_ >= maxIterations) {
-      info_ = ComputationInfo::NoConvergence;
-      return x_;
-    }
-
-    // In exact arithmetic, a positive gradient guarantees that the candidate
-    // column is independent of the inactive (passive) set, so a row-sized set
-    // would have satisfied the stopping condition above. If it does not,
-    // numerical dependence has invalidated that invariant. Another rank-1 QR
-    // update would exceed the row capacity, but the current iterate cannot be
-    // reported as optimal either.
-    if (numInactive_ == A_.rows()) {
-      info_ = ComputationInfo::NumericalIssue;
-      return x_;
-    }
-
-    moveToInactiveSet_(argmaxGradient);
-
-    // INNER LOOP
-    while (true) {
-      // Check if max. number of iterations is reached
-      if (iterations_ >= maxIterations) {
-        info_ = ComputationInfo::NoConvergence;
-        return x_;
-      }
-
-      // Solve least-squares problem in inactive set only,
-      // this step is rather trivial as moveToInactiveSet_ & moveToActiveSet_
-      // updates the QR decomposition of inactive columns A^N.
-      // solveInactiveSet_ puts the solution in y_
-      solveInactiveSet_(b);
-      ++iterations_;  // The solve is expensive, so that is what we count as an iteration.
-      if (!y_.allFinite()) return x_;
-
-      // Check feasibility...
-      bool feasible = true;
-      Scalar alpha = NumTraits<Scalar>::highest();
-      Index infeasibleIdx = -1;  // Which variable became infeasible first.
-      for (Index i = 0; i < numInactive_; i++) {
-        Index idx = index_sets_[i];
-        if (y_(idx) < 0) {
-          // t should always be in [0,1].
-          Scalar t = -x_(idx) / (y_(idx) - x_(idx));
-          if (alpha > t) {
-            alpha = t;
-            infeasibleIdx = i;
-            feasible = false;
-          }
-        }
-      }
-      eigen_assert(feasible || 0 <= infeasibleIdx);
-
-      // If solution is feasible, exit to outer loop
-      if (feasible) {
-        x_ = y_;
-        break;
-      }
-
-      // Infeasible solution -> interpolate to feasible one
-      for (Index i = 0; i < numInactive_; i++) {
-        Index idx = index_sets_[i];
-        x_(idx) += alpha * (y_(idx) - x_(idx));
-      }
-
-      // Remove these indices from the inactive set and update QR decomposition
-      moveToActiveSet_(infeasibleIdx);
-    }
-  }
-}
-
-template <typename MatrixType>
-void NNLS<MatrixType>::moveToInactiveSet_(Index idx) {
-  // Update permutation matrix:
-  std::swap(index_sets_(idx), index_sets_(numInactive_));
-  numInactive_++;
-
-  // Perform rank-1 update of the QR decomposition stored in QR_ & qrCoeff_
-  internal::householder_qr_inplace_update(QR_, qrCoeffs_, A_.col(index_sets_(numInactive_ - 1)), numInactive_ - 1,
-                                          tempSolutionVector_.data());
-}
-
-template <typename MatrixType>
-void NNLS<MatrixType>::moveToActiveSet_(Index idx) {
-  // swap index with last inactive one & reduce number of inactive columns
-  std::swap(index_sets_(idx), index_sets_(numInactive_ - 1));
-  numInactive_--;
-  // Update QR decomposition starting from the removed index up to the end [idx, ..., numInactive_]
-  for (Index i = idx; i < numInactive_; i++) {
-    Index col = index_sets_(i);
-    internal::householder_qr_inplace_update(QR_, qrCoeffs_, A_.col(col), i, tempSolutionVector_.data());
-  }
-}
-
-template <typename MatrixType>
-void NNLS<MatrixType>::solveInactiveSet_(const RhsVectorType &b) {
-  eigen_assert(numInactive_ > 0);
-
-  tempRhsVector_ = b;
-
-  // tmpRHS(0:numInactive_-1) := Q'*b
-  // tmpRHS(numInactive_:end) := useless stuff we would rather not compute at all.
-  tempRhsVector_.applyOnTheLeft(
-      householderSequence(QR_.leftCols(numInactive_), qrCoeffs_.head(numInactive_)).transpose());
-
-  // tempSol(0:numInactive_-1) := inv(R) * Q' * b
-  //  = the least-squares solution for the inactive variables.
-  tempSolutionVector_.head(numInactive_) =            //
-      QR_.topLeftCorner(numInactive_, numInactive_)   //
-          .template triangularView<Upper>()           //
-          .solve(tempRhsVector_.head(numInactive_));  //
-
-  // tempSol(numInactive_:end) := 0 = the value for the constrained variables.
-  tempSolutionVector_.tail(y_.size() - numInactive_).setZero();
-
-  // Back permute into original column order of A
-  y_.noalias() = index_sets_.asPermutation() * tempSolutionVector_.head(y_.size());
-}
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_NNLS_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_NNLS_FORWARD_H
diff --git a/unsupported/Eigen/NonLinearOptimization b/unsupported/Eigen/NonLinearOptimization
index 18a493f..f1b37c7 100644
--- a/unsupported/Eigen/NonLinearOptimization
+++ b/unsupported/Eigen/NonLinearOptimization
@@ -1,146 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/NonLinearOptimization>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_NONLINEAROPTIMIZATION_MODULE_H
-#define EIGEN_NONLINEAROPTIMIZATION_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_NONLINEAROPTIMIZATION_FORWARD_H
+#define EIGEN_UNSUPPORTED_NONLINEAROPTIMIZATION_FORWARD_H
 
-#include <vector>
+#include "../../contrib/Eigen/NonLinearOptimization"  // IWYU pragma: export
 
-#include "../../Eigen/Core"
-#include "../../Eigen/Jacobi"
-#include "../../Eigen/QR"
-#include "NumericalDiff"
-
-/**
- * \defgroup NonLinearOptimization_Module Non linear optimization module
- *
- * \code
- * #include <unsupported/Eigen/NonLinearOptimization>
- * \endcode
- *
- * This module provides implementation of two important algorithms in non linear
- * optimization. In both cases, we consider a system of non linear functions. Of
- * course, this should work, and even work very well if those functions are
- * actually linear. But if this is so, you should probably better use other
- * methods more fitted to this special case.
- *
- * One algorithm allows to find a least-squares solution of such a system
- * (Levenberg-Marquardt algorithm) and the second one is used to find
- * a zero for the system (Powell hybrid "dogleg" method).
- *
- * This code is a port of minpack (http://en.wikipedia.org/wiki/MINPACK).
- * Minpack is a very famous, old, robust and well renowned package, written in
- * fortran. Those implementations have been carefully tuned, tested, and used
- * for several decades.
- *
- * The original fortran code was automatically translated using f2c (http://en.wikipedia.org/wiki/F2c) in C,
- * then c++, and then cleaned by several different authors.
- * The last one of those cleanings being our starting point :
- * http://devernay.free.fr/hacks/cminpack.html
- *
- * Finally, we ported this code to Eigen, creating classes and API
- * coherent with Eigen. When possible, we switched to Eigen
- * implementation, such as most linear algebra (vectors, matrices, stable norms).
- *
- * Doing so, we were very careful to check the tests we setup at the very
- * beginning, which ensure that the same results are found.
- *
- * \section Tests Tests
- *
- * The tests are placed in the file unsupported/test/NonLinear.cpp.
- *
- * There are two kinds of tests : those that come from examples bundled with cminpack.
- * They guaranty we get the same results as the original algorithms (value for 'x',
- * for the number of evaluations of the function, and for the number of evaluations
- * of the Jacobian if ever).
- *
- * Other tests were added by myself at the very beginning of the
- * process and check the results for Levenberg-Marquardt using the reference data
- * on http://www.itl.nist.gov/div898/strd/nls/nls_main.shtml. Since then i've
- * carefully checked that the same results were obtained when modifying the
- * code. Please note that we do not always get the exact same decimals as they do,
- * but this is ok : they use 128bits float, and we do the tests using the C type 'double',
- * which is 64 bits on most platforms (x86 and amd64, at least).
- * I've performed those tests on several other implementations of Levenberg-Marquardt, and
- * (c)minpack performs VERY well compared to those, both in accuracy and speed.
- *
- * The documentation for running the tests is on the wiki
- * http://eigen.tuxfamily.org/index.php?title=Tests
- *
- * \section API API: overview of methods
- *
- * Both algorithms needs a functor computing the Jacobian. It can be computed by
- * hand, using auto-differentiation (see \ref AutoDiff_Module), or using numerical
- * differences (see \ref NumericalDiff_Module). For instance:
- *\code
- * MyFunc func;
- * NumericalDiff<MyFunc> func_with_num_diff(func);
- * LevenbergMarquardt<NumericalDiff<MyFunc> > lm(func_with_num_diff);
- * \endcode
- * For HybridNonLinearSolver, the method solveNumericalDiff() does the above wrapping for
- * you.
- *
- * The methods LevenbergMarquardt.lmder1()/lmdif1()/lmstr1() and
- * HybridNonLinearSolver.hybrj1()/hybrd1() are specific methods from the original
- * minpack package that you probably should NOT use until you are porting a code that
- * was previously using minpack. They just define a 'simple' API with default values
- * for some parameters.
- *
- * All algorithms are provided using two APIs :
- *     - one where the user inits the algorithm, and uses '*OneStep()' as much as he wants :
- * this way the caller have control over the steps
- *     - one where the user just calls a method (optimize() or solve()) which will
- * handle the loop: init + loop until a stop condition is met. Those are provided for
- *  convenience.
- *
- * As an example, the method LevenbergMarquardt::minimize() is
- * implemented as follow:
- * \code
- * Status LevenbergMarquardt<FunctorType,Scalar>::minimize(FVectorType  &x, const int mode)
- * {
- *     Status status = minimizeInit(x, mode);
- *     do {
- *         status = minimizeOneStep(x, mode);
- *     } while (status==Running);
- *     return status;
- * }
- * \endcode
- *
- * \section examples Examples
- *
- * The easiest way to understand how to use this module is by looking at the many examples in the file
- * unsupported/test/NonLinearOptimization.cpp.
- */
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#ifndef EIGEN_PARSED_BY_DOXYGEN
-
-#include "src/NonLinearOptimization/qrsolv.h"
-#include "src/NonLinearOptimization/r1updt.h"
-#include "src/NonLinearOptimization/r1mpyq.h"
-#include "src/NonLinearOptimization/rwupdt.h"
-#include "src/NonLinearOptimization/fdjac1.h"
-#include "src/NonLinearOptimization/lmpar.h"
-#include "src/NonLinearOptimization/dogleg.h"
-#include "src/NonLinearOptimization/covar.h"
-
-#include "src/NonLinearOptimization/chkder.h"
-
-#endif
-
-#include "src/NonLinearOptimization/HybridNonLinearSolver.h"
-#include "src/NonLinearOptimization/LevenbergMarquardt.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_NONLINEAROPTIMIZATION_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_NONLINEAROPTIMIZATION_FORWARD_H
diff --git a/unsupported/Eigen/NumericalDiff b/unsupported/Eigen/NumericalDiff
index 0a41291..ce05349 100644
--- a/unsupported/Eigen/NumericalDiff
+++ b/unsupported/Eigen/NumericalDiff
@@ -1,62 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/NumericalDiff>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_NUMERICALDIFF_MODULE_H
-#define EIGEN_NUMERICALDIFF_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_NUMERICALDIFF_FORWARD_H
+#define EIGEN_UNSUPPORTED_NUMERICALDIFF_FORWARD_H
 
-#include "../../Eigen/Core"
+#include "../../contrib/Eigen/NumericalDiff"  // IWYU pragma: export
 
-namespace Eigen {
-
-/**
- * \defgroup NumericalDiff_Module Numerical differentiation module
- *
- * \code
- * #include <unsupported/Eigen/NumericalDiff>
- * \endcode
- *
- * See http://en.wikipedia.org/wiki/Numerical_differentiation
- *
- * Warning : this should NOT be confused with automatic differentiation, which
- * is a different method and has its own module in Eigen : \ref
- * AutoDiff_Module.
- *
- * Currently only "Forward" and "Central" schemes are implemented. Those
- * are basic methods, and there exist some more elaborated way of
- * computing such approximates. They are implemented using both
- * proprietary and free software, and usually requires linking to an
- * external library. It is very easy for you to write a functor
- * using such software, and the purpose is quite orthogonal to what we
- * want to achieve with Eigen.
- *
- * This is why we will not provide wrappers for every great numerical
- * differentiation software that exist, but should rather stick with those
- * basic ones, that still are useful for testing.
- *
- * Also, the \ref NonLinearOptimization_Module needs this in order to
- * provide full features compatibility with the original (c)minpack
- * package.
- *
- */
-}
-
-//@{
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/NumericalDiff/NumericalDiff.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-//@}
-
-#endif  // EIGEN_NUMERICALDIFF_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_NUMERICALDIFF_FORWARD_H
diff --git a/unsupported/Eigen/OpenGLSupport b/unsupported/Eigen/OpenGLSupport
index ca10408..1061371 100644
--- a/unsupported/Eigen/OpenGLSupport
+++ b/unsupported/Eigen/OpenGLSupport
@@ -1,355 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/OpenGLSupport>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_OPENGL_MODULE_H
-#define EIGEN_OPENGL_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_OPENGLSUPPORT_FORWARD_H
+#define EIGEN_UNSUPPORTED_OPENGLSUPPORT_FORWARD_H
 
-#include "../../Eigen/Geometry"
+#include "../../contrib/Eigen/OpenGLSupport"  // IWYU pragma: export
 
-#if defined(__APPLE_CC__)
-#include <OpenGL/gl.h>
-#else
-#include <GL/gl.h>
-#endif
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/**
- * \defgroup OpenGLSupport_Module OpenGL Support module
- *
- * This module provides wrapper functions for a couple of OpenGL functions
- * which simplify the way to pass Eigen's object to openGL.
- * Here is an example:
- *
- * \code
- * // You need to add path_to_eigen/unsupported to your include path.
- * #include <unsupported/Eigen/OpenGLSupport>
- * // ...
- * Vector3f x, y;
- * Matrix3f rot;
- *
- * glVertex(y + x * rot);
- *
- * Quaternion q;
- * glRotate(q);
- *
- * // ...
- * \endcode
- *
- */
-//@{
-
-#define EIGEN_GL_FUNC_DECLARATION(FUNC)                                                                          \
-  namespace internal {                                                                                           \
-  template <typename XprType, typename Scalar = typename XprType::Scalar, int Rows = XprType::RowsAtCompileTime, \
-            int Cols = XprType::ColsAtCompileTime,                                                               \
-            bool IsGLCompatible = bool(internal::evaluator<XprType>::Flags & LinearAccessBit) &&                 \
-                                  bool(XprType::Flags & DirectAccessBit) &&                                      \
-                                  (XprType::IsVectorAtCompileTime || (XprType::Flags & RowMajorBit) == 0)>       \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl);                                                                 \
-                                                                                                                 \
-  template <typename XprType, typename Scalar, int Rows, int Cols>                                               \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, Scalar, Rows, Cols, false> {                            \
-    inline static void run(const XprType& p) {                                                                   \
-      EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<typename plain_matrix_type_column_major<XprType>::type>::run(p);    \
-    }                                                                                                            \
-  };                                                                                                             \
-  }                                                                                                              \
-                                                                                                                 \
-  template <typename Derived>                                                                                    \
-  inline void FUNC(const Eigen::DenseBase<Derived>& p) {                                                         \
-    EIGEN_CAT(EIGEN_CAT(internal::gl_, FUNC), _impl)<Derived>::run(p.derived());                                 \
-  }
-
-#define EIGEN_GL_FUNC_SPECIALIZATION_MAT(FUNC, SCALAR, ROWS, COLS, SUFFIX)           \
-  namespace internal {                                                               \
-  template <typename XprType>                                                        \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, ROWS, COLS, true> { \
-    inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); }             \
-  };                                                                                 \
-  }
-
-#define EIGEN_GL_FUNC_SPECIALIZATION_VEC(FUNC, SCALAR, SIZE, SUFFIX)              \
-  namespace internal {                                                            \
-  template <typename XprType>                                                     \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, SIZE, 1, true> { \
-    inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); }          \
-  };                                                                              \
-  template <typename XprType>                                                     \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, 1, SIZE, true> { \
-    inline static void run(const XprType& p) { FUNC##SUFFIX(p.data()); }          \
-  };                                                                              \
-  }
-
-EIGEN_GL_FUNC_DECLARATION(glVertex)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, int, 2, 2iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, short, 2, 2sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, float, 2, 2fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, double, 2, 2dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, int, 3, 3iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, short, 3, 3sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, float, 3, 3fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, double, 3, 3dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, int, 4, 4iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, short, 4, 4sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, float, 4, 4fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glVertex, double, 4, 4dv)
-
-EIGEN_GL_FUNC_DECLARATION(glTexCoord)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, int, 2, 2iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, short, 2, 2sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, float, 2, 2fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, double, 2, 2dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, int, 3, 3iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, short, 3, 3sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, float, 3, 3fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, double, 3, 3dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, int, 4, 4iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, short, 4, 4sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, float, 4, 4fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTexCoord, double, 4, 4dv)
-
-EIGEN_GL_FUNC_DECLARATION(glColor)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, int, 2, 2iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, short, 2, 2sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, float, 2, 2fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, double, 2, 2dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, int, 3, 3iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, short, 3, 3sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, float, 3, 3fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, double, 3, 3dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, int, 4, 4iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, short, 4, 4sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, float, 4, 4fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glColor, double, 4, 4dv)
-
-EIGEN_GL_FUNC_DECLARATION(glNormal)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, int, 3, 3iv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, short, 3, 3sv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, float, 3, 3fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glNormal, double, 3, 3dv)
-
-inline void glScale2fv(const float* v) { glScalef(v[0], v[1], 1.f); }
-inline void glScale2dv(const double* v) { glScaled(v[0], v[1], 1.0); }
-inline void glScale3fv(const float* v) { glScalef(v[0], v[1], v[2]); }
-inline void glScale3dv(const double* v) { glScaled(v[0], v[1], v[2]); }
-
-EIGEN_GL_FUNC_DECLARATION(glScale)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, float, 2, 2fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, double, 2, 2dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, float, 3, 3fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glScale, double, 3, 3dv)
-
-template <typename Scalar>
-void glScale(const UniformScaling<Scalar>& s) {
-  glScale(Matrix<Scalar, 3, 1>::Constant(s.factor()));
-}
-
-inline void glTranslate2fv(const float* v) { glTranslatef(v[0], v[1], 0.f); }
-inline void glTranslate2dv(const double* v) { glTranslated(v[0], v[1], 0.0); }
-inline void glTranslate3fv(const float* v) { glTranslatef(v[0], v[1], v[2]); }
-inline void glTranslate3dv(const double* v) { glTranslated(v[0], v[1], v[2]); }
-
-EIGEN_GL_FUNC_DECLARATION(glTranslate)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, float, 2, 2fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, double, 2, 2dv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, float, 3, 3fv)
-EIGEN_GL_FUNC_SPECIALIZATION_VEC(glTranslate, double, 3, 3dv)
-
-template <typename Scalar>
-void glTranslate(const Translation<Scalar, 2>& t) {
-  glTranslate(t.vector());
-}
-template <typename Scalar>
-void glTranslate(const Translation<Scalar, 3>& t) {
-  glTranslate(t.vector());
-}
-
-EIGEN_GL_FUNC_DECLARATION(glMultMatrix)
-EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix, float, 4, 4, f)
-EIGEN_GL_FUNC_SPECIALIZATION_MAT(glMultMatrix, double, 4, 4, d)
-
-template <typename Scalar>
-void glMultMatrix(const Transform<Scalar, 3, Affine>& t) {
-  glMultMatrix(t.matrix());
-}
-template <typename Scalar>
-void glMultMatrix(const Transform<Scalar, 3, Projective>& t) {
-  glMultMatrix(t.matrix());
-}
-template <typename Scalar>
-void glMultMatrix(const Transform<Scalar, 3, AffineCompact>& t) {
-  glMultMatrix(Transform<Scalar, 3, Affine>(t).matrix());
-}
-
-EIGEN_GL_FUNC_DECLARATION(glLoadMatrix)
-EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix, float, 4, 4, f)
-EIGEN_GL_FUNC_SPECIALIZATION_MAT(glLoadMatrix, double, 4, 4, d)
-
-template <typename Scalar>
-void glLoadMatrix(const Transform<Scalar, 3, Affine>& t) {
-  glLoadMatrix(t.matrix());
-}
-template <typename Scalar>
-void glLoadMatrix(const Transform<Scalar, 3, Projective>& t) {
-  glLoadMatrix(t.matrix());
-}
-template <typename Scalar>
-void glLoadMatrix(const Transform<Scalar, 3, AffineCompact>& t) {
-  glLoadMatrix(Transform<Scalar, 3, Affine>(t).matrix());
-}
-
-inline void glRotate(const Rotation2D<float>& rot) { glRotatef(rot.angle() * 180.f / float(EIGEN_PI), 0.f, 0.f, 1.f); }
-inline void glRotate(const Rotation2D<double>& rot) {
-  glRotated(rot.angle() * 180.0 / double(EIGEN_PI), 0.0, 0.0, 1.0);
-}
-
-template <typename Derived>
-void glRotate(const RotationBase<Derived, 3>& rot) {
-  Transform<typename Derived::Scalar, 3, Projective> tr(rot);
-  glMultMatrix(tr.matrix());
-}
-
-#define EIGEN_GL_MAKE_CONST_const const
-#define EIGEN_GL_MAKE_CONST__
-#define EIGEN_GL_EVAL(X) X
-
-#define EIGEN_GL_FUNC1_DECLARATION(FUNC, ARG1, CONST)                                                            \
-  namespace internal {                                                                                           \
-  template <typename XprType, typename Scalar = typename XprType::Scalar, int Rows = XprType::RowsAtCompileTime, \
-            int Cols = XprType::ColsAtCompileTime,                                                               \
-            bool IsGLCompatible = bool(internal::evaluator<XprType>::Flags & LinearAccessBit) &&                 \
-                                  bool(XprType::Flags & DirectAccessBit) &&                                      \
-                                  (XprType::IsVectorAtCompileTime || (XprType::Flags & RowMajorBit) == 0)>       \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl);                                                                 \
-                                                                                                                 \
-  template <typename XprType, typename Scalar, int Rows, int Cols>                                               \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, Scalar, Rows, Cols, false> {                            \
-    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) {                      \
-      EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<typename plain_matrix_type_column_major<XprType>::type>::run(a, p); \
-    }                                                                                                            \
-  };                                                                                                             \
-  }                                                                                                              \
-                                                                                                                 \
-  template <typename Derived>                                                                                    \
-  inline void FUNC(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) Eigen::DenseBase<Derived>& p) {            \
-    EIGEN_CAT(EIGEN_CAT(internal::gl_, FUNC), _impl)<Derived>::run(a, p.derived());                              \
-  }
-
-#define EIGEN_GL_FUNC1_SPECIALIZATION_MAT(FUNC, ARG1, CONST, SCALAR, ROWS, COLS, SUFFIX)    \
-  namespace internal {                                                                      \
-  template <typename XprType>                                                               \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, ROWS, COLS, true> {        \
-    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
-      FUNC##SUFFIX(a, p.data());                                                            \
-    }                                                                                       \
-  };                                                                                        \
-  }
-
-#define EIGEN_GL_FUNC1_SPECIALIZATION_VEC(FUNC, ARG1, CONST, SCALAR, SIZE, SUFFIX)          \
-  namespace internal {                                                                      \
-  template <typename XprType>                                                               \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, SIZE, 1, true> {           \
-    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
-      FUNC##SUFFIX(a, p.data());                                                            \
-    }                                                                                       \
-  };                                                                                        \
-  template <typename XprType>                                                               \
-  struct EIGEN_CAT(EIGEN_CAT(gl_, FUNC), _impl)<XprType, SCALAR, 1, SIZE, true> {           \
-    inline static void run(ARG1 a, EIGEN_GL_EVAL(EIGEN_GL_MAKE_CONST_##CONST) XprType& p) { \
-      FUNC##SUFFIX(a, p.data());                                                            \
-    }                                                                                       \
-  };                                                                                        \
-  }
-
-EIGEN_GL_FUNC1_DECLARATION(glGet, GLenum, _)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glGet, GLenum, _, float, 4, 4, Floatv)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glGet, GLenum, _, double, 4, 4, Doublev)
-
-// glUniform API
-
-#ifdef GL_VERSION_2_0
-
-inline void glUniform2fv_ei(GLint loc, const float* v) { glUniform2fv(loc, 1, v); }
-inline void glUniform2iv_ei(GLint loc, const int* v) { glUniform2iv(loc, 1, v); }
-
-inline void glUniform3fv_ei(GLint loc, const float* v) { glUniform3fv(loc, 1, v); }
-inline void glUniform3iv_ei(GLint loc, const int* v) { glUniform3iv(loc, 1, v); }
-
-inline void glUniform4fv_ei(GLint loc, const float* v) { glUniform4fv(loc, 1, v); }
-inline void glUniform4iv_ei(GLint loc, const int* v) { glUniform4iv(loc, 1, v); }
-
-inline void glUniformMatrix2fv_ei(GLint loc, const float* v) { glUniformMatrix2fv(loc, 1, false, v); }
-inline void glUniformMatrix3fv_ei(GLint loc, const float* v) { glUniformMatrix3fv(loc, 1, false, v); }
-inline void glUniformMatrix4fv_ei(GLint loc, const float* v) { glUniformMatrix4fv(loc, 1, false, v); }
-
-EIGEN_GL_FUNC1_DECLARATION(glUniform, GLint, const)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, float, 2, 2fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, int, 2, 2iv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, float, 3, 3fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, int, 3, 3iv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, float, 4, 4fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, int, 4, 4iv_ei)
-
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 2, 2, Matrix2fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 3, 3, Matrix3fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 4, 4, Matrix4fv_ei)
-
-#endif
-
-#ifdef GL_VERSION_2_1
-
-inline void glUniformMatrix2x3fv_ei(GLint loc, const float* v) { glUniformMatrix2x3fv(loc, 1, false, v); }
-inline void glUniformMatrix3x2fv_ei(GLint loc, const float* v) { glUniformMatrix3x2fv(loc, 1, false, v); }
-inline void glUniformMatrix2x4fv_ei(GLint loc, const float* v) { glUniformMatrix2x4fv(loc, 1, false, v); }
-inline void glUniformMatrix4x2fv_ei(GLint loc, const float* v) { glUniformMatrix4x2fv(loc, 1, false, v); }
-inline void glUniformMatrix3x4fv_ei(GLint loc, const float* v) { glUniformMatrix3x4fv(loc, 1, false, v); }
-inline void glUniformMatrix4x3fv_ei(GLint loc, const float* v) { glUniformMatrix4x3fv(loc, 1, false, v); }
-
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 2, 3, Matrix2x3fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 3, 2, Matrix3x2fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 2, 4, Matrix2x4fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 4, 2, Matrix4x2fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 3, 4, Matrix3x4fv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_MAT(glUniform, GLint, const, float, 4, 3, Matrix4x3fv_ei)
-
-#endif
-
-#ifdef GL_VERSION_3_0
-
-inline void glUniform2uiv_ei(GLint loc, const unsigned int* v) { glUniform2uiv(loc, 1, v); }
-inline void glUniform3uiv_ei(GLint loc, const unsigned int* v) { glUniform3uiv(loc, 1, v); }
-inline void glUniform4uiv_ei(GLint loc, const unsigned int* v) { glUniform4uiv(loc, 1, v); }
-
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, unsigned int, 2, 2uiv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, unsigned int, 3, 3uiv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, unsigned int, 4, 4uiv_ei)
-
-#endif
-
-#ifdef GL_ARB_gpu_shader_fp64
-inline void glUniform2dv_ei(GLint loc, const double* v) { glUniform2dv(loc, 1, v); }
-inline void glUniform3dv_ei(GLint loc, const double* v) { glUniform3dv(loc, 1, v); }
-inline void glUniform4dv_ei(GLint loc, const double* v) { glUniform4dv(loc, 1, v); }
-
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, double, 2, 2dv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, double, 3, 3dv_ei)
-EIGEN_GL_FUNC1_SPECIALIZATION_VEC(glUniform, GLint, const, double, 4, 4dv_ei)
-#endif
-
-//@}
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_OPENGL_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_OPENGLSUPPORT_FORWARD_H
diff --git a/unsupported/Eigen/Polynomials b/unsupported/Eigen/Polynomials
index d6ca037..ddf1f85 100644
--- a/unsupported/Eigen/Polynomials
+++ b/unsupported/Eigen/Polynomials
@@ -1,142 +1,17 @@
 // 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/Polynomials>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_POLYNOMIALS_MODULE_H
-#define EIGEN_POLYNOMIALS_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_POLYNOMIALS_FORWARD_H
+#define EIGEN_UNSUPPORTED_POLYNOMIALS_FORWARD_H
 
-#include "../../Eigen/Core"
+#include "../../contrib/Eigen/Polynomials"  // IWYU pragma: export
 
-#include "../../Eigen/Eigenvalues"
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module
-#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS >= 2)
-#ifndef EIGEN_HIDE_HEAVY_CODE
-#define EIGEN_HIDE_HEAVY_CODE
-#endif
-#elif defined EIGEN_HIDE_HEAVY_CODE
-#undef EIGEN_HIDE_HEAVY_CODE
-#endif
-
-/**
- * \defgroup Polynomials_Module Polynomials module
- * \brief This module provides a QR based polynomial solver.
- *
- * To use this module, add
- * \code
- * #include <unsupported/Eigen/Polynomials>
- * \endcode
- * at the start of your source file.
- */
-
-// IWYU pragma: begin_exports
-#include "src/Polynomials/PolynomialUtils.h"
-#include "src/Polynomials/Companion.h"
-#include "src/Polynomials/PolynomialSolver.h"
-// IWYU pragma: end_exports
-
-/**
-        \page polynomials Polynomials defines functions for dealing with polynomials
-        and a QR based polynomial solver.
-        \ingroup Polynomials_Module
-
-        The remainder of the page documents first the functions for evaluating, computing
-        polynomials, computing estimates about polynomials and next the QR based polynomial
-        solver.
-
-        \section polynomialUtils convenient functions to deal with polynomials
-        \subsection roots_to_monicPolynomial
-        The function
-        \code
-        void roots_to_monicPolynomial( const RootVector& rv, Polynomial& poly )
-        \endcode
-        computes the coefficients \f$ a_i \f$ of
-
-        \f$ p(x) = a_0 + a_{1}x + ... + a_{n-1}x^{n-1} + x^n \f$
-
-        where \f$ p \f$ is known through its roots i.e. \f$ p(x) = (x-r_1)(x-r_2)...(x-r_n) \f$.
-
-        \subsection poly_eval
-        The function
-        \code
-        T poly_eval( const Polynomials& poly, const T& x )
-        \endcode
-        evaluates a polynomial at a given point using stabilized H&ouml;rner method.
-
-        The following code: first computes the coefficients in the monomial basis of the monic polynomial that has the
-  provided roots; then, it evaluates the computed polynomial, using a stabilized H&ouml;rner method.
-
-        \include PolynomialUtils1.cpp
-  Output: \verbinclude PolynomialUtils1.out
-
-        \subsection Cauchy bounds
-        The function
-        \code
-        Real cauchy_max_bound( const Polynomial& poly )
-        \endcode
-        provides a maximum bound (the Cauchy one: \f$C(p)\f$) for the absolute value of a root of the given polynomial
-  i.e. \f$ \forall r_i \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$, \f$ |r_i| \le C(p) = \sum_{k=0}^{d} \left |
-  \frac{a_k}{a_d} \right | \f$ The leading coefficient \f$ p \f$: should be non zero \f$a_d \neq 0\f$.
-
-
-        The function
-        \code
-        Real cauchy_min_bound( const Polynomial& poly )
-        \endcode
-        provides a minimum bound (the Cauchy one: \f$c(p)\f$) for the absolute value of a non zero root of the given
-  polynomial i.e. \f$ \forall r_i \neq 0 \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$, \f$ |r_i| \ge c(p) = \left(
-  \sum_{k=0}^{d} \left | \frac{a_k}{a_0} \right | \right)^{-1} \f$
-
-
-
-
-        \section QR polynomial solver class
-        Computes the complex roots of a polynomial by computing the eigenvalues of the associated companion matrix with
-  the QR algorithm.
-
-        The roots of \f$ p(x) = a_0 + a_1 x + a_2 x^2 + a_{3} x^3 + x^4 \f$ are the eigenvalues of
-        \f$
-        \left [
-        \begin{array}{cccc}
-        0 & 0 &  0 & a_0 \\
-        1 & 0 &  0 & a_1 \\
-        0 & 1 &  0 & a_2 \\
-        0 & 0 &  1 & a_3
-        \end{array} \right ]
-        \f$
-
-        However, the QR algorithm is not guaranteed to converge when there are several eigenvalues with same modulus.
-
-        Therefore the current polynomial solver is guaranteed to provide a correct result only when the complex roots
-  \f$r_1,r_2,...,r_d\f$ have distinct moduli i.e.
-
-        \f$ \forall i,j \in [1;d],~ \| r_i \| \neq \| r_j \| \f$.
-
-        With 32bit (float) floating types this problem shows up frequently.
-  However, almost always, correct accuracy is reached even in these cases for 64bit
-  (double) floating types and small polynomial degree (<20).
-
-        \include PolynomialSolver1.cpp
-
-        In the above example:
-
-        -# a simple use of the polynomial solver is shown;
-        -# the accuracy problem with the QR algorithm is presented: a polynomial with almost conjugate roots is provided
-  to the solver. Those roots have almost same module therefore the QR algorithm failed to converge: the accuracy of the
-  last root is bad;
-        -# a simple way to circumvent the problem is shown: use doubles instead of floats.
-
-  Output: \verbinclude PolynomialSolver1.out
-*/
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_POLYNOMIALS_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_POLYNOMIALS_FORWARD_H
diff --git a/unsupported/Eigen/SparseExtra b/unsupported/Eigen/SparseExtra
index 0758beb..2674df1 100644
--- a/unsupported/Eigen/SparseExtra
+++ b/unsupported/Eigen/SparseExtra
@@ -1,61 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/SparseExtra>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_SPARSE_EXTRA_MODULE_H
-#define EIGEN_SPARSE_EXTRA_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_SPARSEEXTRA_FORWARD_H
+#define EIGEN_UNSUPPORTED_SPARSEEXTRA_FORWARD_H
 
-#include "../../Eigen/Sparse"
+#include "../../contrib/Eigen/SparseExtra"  // IWYU pragma: export
 
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-#include <vector>
-#include <map>
-#include <unordered_map>
-#include <cstdlib>
-#include <cstring>
-#include <algorithm>
-#include <fstream>
-#include <sstream>
-
-#ifdef EIGEN_GOOGLEHASH_SUPPORT
-#include <google/dense_hash_map>
-#include <google/sparse_hash_map>
-#endif
-
-/**
- * \defgroup SparseExtra_Module SparseExtra module
- *
- * This module contains some experimental features extending the sparse module:
- * - A RandomSetter which is a wrapper object allowing to set/update a sparse matrix with random access.
- * - A SparseInverse which calculates a sparse subset of the inverse of a sparse matrix corresponding to nonzeros of the
- * input
- * - MatrixMarket format(https://math.nist.gov/MatrixMarket/formats.html) readers and writers for sparse and dense
- * matrices.
- *
- * \code
- * #include <unsupported/Eigen/SparseExtra>
- * \endcode
- */
-
-// IWYU pragma: begin_exports
-#include "src/SparseExtra/RandomSetter.h"
-#include "src/SparseExtra/SparseInverse.h"
-
-#include "src/SparseExtra/MarketIO.h"
-
-#if !defined(_WIN32)
-#include <dirent.h>
-#include "src/SparseExtra/MatrixMarketIterator.h"
-#endif
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_SPARSE_EXTRA_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_SPARSEEXTRA_FORWARD_H
diff --git a/unsupported/Eigen/SpecialFunctions b/unsupported/Eigen/SpecialFunctions
index 7052054..45189ca 100644
--- a/unsupported/Eigen/SpecialFunctions
+++ b/unsupported/Eigen/SpecialFunctions
@@ -1,114 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2016 Gael Guennebaud <g.gael@free.fr>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/SpecialFunctions>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_SPECIALFUNCTIONS_MODULE_H
-#define EIGEN_SPECIALFUNCTIONS_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_SPECIALFUNCTIONS_FORWARD_H
+#define EIGEN_UNSUPPORTED_SPECIALFUNCTIONS_FORWARD_H
 
-#include <cmath>
+#include "../../contrib/Eigen/SpecialFunctions"  // IWYU pragma: export
 
-#include "../../Eigen/Core"
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-namespace Eigen {
-
-/**
- * \defgroup SpecialFunctions_Module Special math functions module
- *
- * This module features additional coefficient-wise math functions available
- * within the numext:: namespace for the scalar version, and as method and/or free
- * functions of Array. Those include:
- *
- * - erf
- * - erfc
- * - lgamma
- * - igamma
- * - igamma_der_a
- * - gamma_sample_der_alpha
- * - igammac
- * - digamma
- * - ndtri
- * - polygamma
- * - zeta
- * - betainc
- *
- * Bessel Functions
- * - bessel_i0
- * - bessel_i0e
- * - bessel_i1
- * - bessel_i1e
- * - bessel_j0
- * - bessel_j1
- * - bessel_k0
- * - bessel_k0e
- * - bessel_k1
- * - bessel_k1e
- * - bessel_y0
- * - bessel_y1
- *
- * The implementations are tuned for \c float and \c double, so they do not carry
- * over to an arbitrary scalar. \c erf and \c erfc accept any other scalar type
- * that declares its own \c erf / \c erfc in the namespace of that type, where
- * argument-dependent lookup finds it; a scalar type that declares neither is
- * rejected at compile time.
- *
- * \code
- * #include <unsupported/Eigen/SpecialFunctions>
- * \endcode
- */
-//@{
-
-}  // namespace Eigen
-
-// IWYU pragma: begin_exports
-#include "src/SpecialFunctions/BesselFunctionsImpl.h"
-#include "src/SpecialFunctions/BesselFunctionsBFloat16.h"
-#include "src/SpecialFunctions/BesselFunctionsHalf.h"
-#include "src/SpecialFunctions/BesselFunctionsPacketMath.h"
-#include "src/SpecialFunctions/BesselFunctionsFunctors.h"
-#include "src/SpecialFunctions/BesselFunctionsArrayAPI.h"
-#include "src/SpecialFunctions/SpecialFunctionsImpl.h"
-#if defined(EIGEN_HIPCC)
-#include "src/SpecialFunctions/HipVectorCompatibility.h"
-#endif
-#include "src/SpecialFunctions/SpecialFunctionsBFloat16.h"
-#include "src/SpecialFunctions/SpecialFunctionsHalf.h"
-#include "src/SpecialFunctions/SpecialFunctionsPacketMath.h"
-#include "src/SpecialFunctions/SpecialFunctionsFunctors.h"
-#include "src/SpecialFunctions/SpecialFunctionsArrayAPI.h"
-
-#ifndef EIGEN_VECTORIZE_GENERIC
-// TODO(rmlarsen): Make these work with generic vectorization if possible.
-#if defined EIGEN_VECTORIZE_AVX512
-#include "src/SpecialFunctions/arch/AVX/BesselFunctions.h"
-#include "src/SpecialFunctions/arch/AVX/SpecialFunctions.h"
-#include "src/SpecialFunctions/arch/AVX512/BesselFunctions.h"
-#include "src/SpecialFunctions/arch/AVX512/SpecialFunctions.h"
-#elif defined EIGEN_VECTORIZE_AVX
-#include "src/SpecialFunctions/arch/AVX/BesselFunctions.h"
-#include "src/SpecialFunctions/arch/AVX/SpecialFunctions.h"
-#elif defined EIGEN_VECTORIZE_NEON || defined EIGEN_VECTORIZE_SME
-#include "src/SpecialFunctions/arch/NEON/BesselFunctions.h"
-#include "src/SpecialFunctions/arch/NEON/SpecialFunctions.h"
-#endif
-
-#if defined EIGEN_VECTORIZE_GPU
-#include "src/SpecialFunctions/arch/GPU/SpecialFunctions.h"
-#endif
-#endif
-// IWYU pragma: end_exports
-
-namespace Eigen {
-//@}
-}
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_SPECIALFUNCTIONS_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_SPECIALFUNCTIONS_FORWARD_H
diff --git a/unsupported/Eigen/Splines b/unsupported/Eigen/Splines
index 721d5d7..6587f37 100644
--- a/unsupported/Eigen/Splines
+++ b/unsupported/Eigen/Splines
@@ -1,39 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2010-2011 Hauke Heibel <hauke.heibel@gmail.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-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/Splines>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_SPLINES_MODULE_H
-#define EIGEN_SPLINES_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_SPLINES_FORWARD_H
+#define EIGEN_UNSUPPORTED_SPLINES_FORWARD_H
 
-#include "../../Eigen/Core"
+#include "../../contrib/Eigen/Splines"  // IWYU pragma: export
 
-namespace Eigen {
-/**
- * \defgroup Splines_Module Spline and spline fitting module
- *
- * This module provides a simple multi-dimensional spline class while
- * offering most basic functionality to fit a spline to point sets.
- *
- * \code
- * #include <unsupported/Eigen/Splines>
- * \endcode
- */
-}
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/Splines/SplineFwd.h"
-#include "src/Splines/Spline.h"
-#include "src/Splines/SplineFitting.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_SPLINES_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_SPLINES_FORWARD_H
diff --git a/unsupported/Eigen/StructuredMatrices b/unsupported/Eigen/StructuredMatrices
index 310beca..3f5f268 100644
--- a/unsupported/Eigen/StructuredMatrices
+++ b/unsupported/Eigen/StructuredMatrices
@@ -1,95 +1,17 @@
 // 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/StructuredMatrices>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_STRUCTURED_MATRICES_MODULE_H
-#define EIGEN_STRUCTURED_MATRICES_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_STRUCTUREDMATRICES_FORWARD_H
+#define EIGEN_UNSUPPORTED_STRUCTUREDMATRICES_FORWARD_H
 
-#include "../../Eigen/Core"
-#include "../../Eigen/Eigenvalues"
-#include "../../Eigen/LU"
-#include "../../Eigen/SVD"
-#include "../../Eigen/IterativeLinearSolvers"
-#include "FFT"
+#include "../../contrib/Eigen/StructuredMatrices"  // IWYU pragma: export
 
-namespace Eigen {
-
-/**
- * \defgroup StructuredMatrices_Module StructuredMatrices module
- *
- * This module provides lightweight operator types for displacement-structured
- * matrices together with fast matrix-vector products and direct solvers:
- *   - \c Circulant : a circulant matrix, diagonalized by the DFT;
- *   - \c Toeplitz  : a (possibly rectangular) Toeplitz matrix, multiplied in
- *     O(n log n) via circulant embedding;
- *   - \c Hankel    : a (possibly rectangular) Hankel matrix -- a column-reversed
- *     Toeplitz matrix -- with the same O(n log n) products, and square solves
- *     through the Toeplitz equivalent;
- *   - \c KroneckerOperator : the Kronecker product of two dense or diagonal
- *     matrices as an implicit operator; products, solves, least squares,
- *     eigendecomposition, SVD, inverse and determinant all factor through the
- *     operands, and diagonal (in particular identity) factors are stored and
- *     applied in diagonal form;
- *   - \c DiagonalPlusLowRank : a diagonal matrix plus a rank-k correction, with
- *     O(nk) products and O(nk^2) Woodbury solves, closed under inversion;
- *   - \c Vandermonde : a Vandermonde matrix stored as its nodes, with Horner
- *     products and O(n^2) Björck-Pereyra primal/dual solves
- *     (\c BjorckPereyra).
- *
- * The operator types derive from \c EigenBase and store only compact generators
- * or factors. The FFT-backed operators (\c Circulant, \c Toeplitz and \c Hankel)
- * also keep a precomputed DFT symbol that every product reuses.
- * The operator types derive from \c EigenBase and store only their generating
- * vectors; the FFT-backed operators (\c Circulant, \c Toeplitz, \c Bccb) also
- * keep a precomputed DFT symbol that every product reuses.
- * Because they expose \c operator* returning an Eigen product expression, they
- * also plug directly into the matrix-free iterative solvers
- * (\c ConjugateGradient, \c GMRES, \c MINRES, ...) without forming the dense
- * matrix; and since they hook into the evaluator system, they can be assigned
- * to a dense matrix when an explicit representation is needed. Like every
- * matrix-free operator, they carry no coefficient storage the default
- * preconditioners could read, so the iterative solvers must be instantiated
- * with \c IdentityPreconditioner.
- *
- * All operator types are closed under transposition (\c transpose(),
- * \c conjugate(), \c adjoint() return operators of the same kind, the FFT-based
- * ones reusing the cached symbol), which in particular feeds the least-squares
- * solvers \c LSMR and \c LeastSquaresConjugateGradient (again with
- * \c IdentityPreconditioner).
- * The \c Circulant, \c Toeplitz and \c Hankel operators are closed under
- * transposition (\c transpose(),
- * \c conjugate(), \c adjoint() return operators of the same kind, reusing the
- * cached symbol), which in particular feeds the least-squares solvers \c LSMR
- * and \c LeastSquaresConjugateGradient (again with \c IdentityPreconditioner).
- * \c Circulant additionally exposes its closed-form eigendecomposition and SVD
- * in the Fourier basis, a pseudo-inverse (minimum-norm least-squares) solve,
- * \c rank(), \c inverse() and \c determinant().
- *
- * \code
- * #include <unsupported/Eigen/StructuredMatrices>
- * \endcode
- */
-
-}  // namespace Eigen
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "src/StructuredMatrices/StructuredMatrixUtils.h"
-#include "src/StructuredMatrices/Circulant.h"
-#include "src/StructuredMatrices/Toeplitz.h"
-#include "src/StructuredMatrices/LookAheadLevinson.h"
-#include "src/StructuredMatrices/Hankel.h"
-#include "src/StructuredMatrices/KroneckerOperator.h"
-#include "src/StructuredMatrices/DiagonalPlusLowRank.h"
-#include "src/StructuredMatrices/Vandermonde.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_STRUCTURED_MATRICES_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_STRUCTUREDMATRICES_FORWARD_H
diff --git a/unsupported/Eigen/Tensor b/unsupported/Eigen/Tensor
index db13ef6..7e5d6c0 100644
--- a/unsupported/Eigen/Tensor
+++ b/unsupported/Eigen/Tensor
@@ -1,159 +1,14 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
-// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/Tensor>
+// directly. This shim preserves the legacy include path.
 
-// A later inclusion can complete a device type after its backend macro is
-// enabled. Backend evaluation still requires the macro before including Eigen.
-#if !defined(EIGEN_TENSOR_MODULE_H) || (defined(EIGEN_USE_THREADS) && !defined(EIGEN_TENSOR_MODULE_THREADS_LOADED)) || \
-    (defined(EIGEN_USE_GPU) && !defined(EIGEN_TENSOR_MODULE_GPU_LOADED)) ||                                            \
-    (defined(EIGEN_USE_SYCL) && !defined(EIGEN_TENSOR_MODULE_SYCL_LOADED))
-#define EIGEN_TENSOR_MODULE_H
-
-// Record caller-provided backend macros before any included header can change
-// them, so later inclusions detect only backends newly enabled by the caller.
-#ifdef EIGEN_USE_THREADS
-#define EIGEN_TENSOR_MODULE_THREADS_LOADED
-#endif
-#ifdef EIGEN_USE_GPU
-#define EIGEN_TENSOR_MODULE_GPU_LOADED
-#endif
-#ifdef EIGEN_USE_SYCL
-#define EIGEN_TENSOR_MODULE_SYCL_LOADED
-#endif
-
-#include "../../Eigen/Core"
-
-#include "SpecialFunctions"
-
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-// IWYU pragma: begin_exports
-#include "../../Eigen/src/Core/util/Meta.h"
-#include "../../Eigen/src/Core/util/MaxSizeVector.h"
-// IWYU pragma: end_exports
-
-/** \defgroup Tensor_Module Tensor Module
- *
- * This module provides a Tensor class for storing arbitrarily indexed
- * objects.
- *
- * \code
- * #include <unsupported/Eigen/Tensor>
- * \endcode
- *
- * Much of the documentation can be found \ref eigen_tensors "here".
- */
-
-#include <atomic>
-#include <chrono>
-#include <cmath>
-#include <cstddef>
-#include <cstring>
-#include <iterator>
-#include <numeric>
-#include <random>
-#include <thread>
-
-#if defined(EIGEN_USE_THREADS) || defined(EIGEN_USE_SYCL)
-#include "../../Eigen/ThreadPool"
-#endif
-
-#ifdef EIGEN_USE_GPU
-#include <iostream>
-#if defined(EIGEN_USE_HIP)
-#include <hip/hip_runtime.h>
-#else
-#include <cuda_runtime.h>
-#endif
-#endif
-
-// IWYU pragma: begin_exports
-#include "src/Tensor/TensorMacros.h"
-#include "src/Tensor/TensorForwardDeclarations.h"
-#include "src/Tensor/TensorMeta.h"
-#include "src/Tensor/TensorFunctors.h"
-#include "src/Tensor/TensorCostModel.h"
-#include "src/Tensor/TensorDeviceDefault.h"
-#include "src/Tensor/TensorDeviceThreadPool.h"
-#include "src/Tensor/TensorDeviceGpu.h"
-#ifndef gpu_assert
-#define gpu_assert(x)
-#endif
-#include "src/Tensor/TensorDeviceSycl.h"
-#include "src/Tensor/TensorIndexList.h"
-#include "src/Tensor/TensorDimensionList.h"
-#include "src/Tensor/TensorDimensions.h"
-#include "src/Tensor/TensorInitializer.h"
-#include "src/Tensor/TensorTraits.h"
-#include "src/Tensor/TensorRandom.h"
-#include "src/Tensor/TensorUInt128.h"
-#include "src/Tensor/TensorIntDiv.h"
-#include "src/Tensor/TensorGlobalFunctions.h"
-
-#include "src/Tensor/TensorIO.h"
-
-#include "src/Tensor/TensorBase.h"
-#include "src/Tensor/TensorBlock.h"
-
-#include "src/Tensor/TensorEvaluator.h"
-#include "src/Tensor/TensorExpr.h"
-#include "src/Tensor/TensorReduction.h"
-#include "src/Tensor/TensorReductionGpu.h"
-#include "src/Tensor/TensorArgMax.h"
-#include "src/Tensor/TensorConcatenation.h"
-#include "src/Tensor/TensorContractionMapper.h"
-#include "src/Tensor/TensorContractionBlocking.h"
-#include "src/Tensor/TensorContraction.h"
-#include "src/Tensor/TensorContractionThreadPool.h"
-#include "src/Tensor/TensorContractionGpu.h"
-#include "src/Tensor/TensorConversion.h"
-#include "src/Tensor/TensorConvolution.h"
-#include "src/Tensor/TensorFFT.h"
-#include "src/Tensor/TensorPatch.h"
-#include "src/Tensor/TensorImagePatch.h"
-#include "src/Tensor/TensorVolumePatch.h"
-#include "src/Tensor/TensorBroadcasting.h"
-#include "src/Tensor/TensorChipping.h"
-#include "src/Tensor/TensorInflation.h"
-#include "src/Tensor/TensorLayoutSwap.h"
-#include "src/Tensor/TensorMorphing.h"
-#include "src/Tensor/TensorPadding.h"
-#include "src/Tensor/TensorReverse.h"
-#include "src/Tensor/TensorRoll.h"
-#include "src/Tensor/TensorShuffling.h"
-#include "src/Tensor/TensorStriding.h"
-#include "src/Tensor/TensorCustomOp.h"
-#include "src/Tensor/TensorEvalTo.h"
-#include "src/Tensor/TensorForcedEval.h"
-#include "src/Tensor/TensorGenerator.h"
-#include "src/Tensor/TensorAssign.h"
-#include "src/Tensor/TensorScan.h"
-#include "src/Tensor/TensorTrace.h"
-
-#ifdef EIGEN_USE_SYCL
-#include "src/Tensor/TensorReductionSycl.h"
-#include "src/Tensor/TensorConvolutionSycl.h"
-#include "src/Tensor/TensorContractionSycl.h"
-#include "src/Tensor/TensorScanSycl.h"
-#endif
-
-#include "src/Tensor/TensorExecutor.h"
-#include "src/Tensor/TensorDevice.h"
-
-#include "src/Tensor/TensorStorage.h"
-#include "src/Tensor/Tensor.h"
-#include "src/Tensor/TensorFixedSize.h"
-#include "src/Tensor/TensorMap.h"
-#include "src/Tensor/TensorRef.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // Tensor module or newly enabled backend
+// Forward every inclusion so the Tensor module can detect a newly enabled
+// backend and complete its device type.
+#include "../../contrib/Eigen/Tensor"  // IWYU pragma: export
diff --git a/unsupported/Eigen/TensorSymmetry b/unsupported/Eigen/TensorSymmetry
index da1c007..8e454e3 100644
--- a/unsupported/Eigen/TensorSymmetry
+++ b/unsupported/Eigen/TensorSymmetry
@@ -1,39 +1,17 @@
 // This file is part of Eigen, a lightweight C++ template library
 // for linear algebra.
 //
-// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
-//
-// 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
+//
+// Forwarding header: the top-level unsupported/ directory was renamed
+// to contrib/ in Eigen 5.x. New code should use
+//   #include <contrib/Eigen/TensorSymmetry>
+// directly. This shim preserves the legacy include path.
 
-#ifndef EIGEN_TENSORSYMMETRY_MODULE_H
-#define EIGEN_TENSORSYMMETRY_MODULE_H
+#ifndef EIGEN_UNSUPPORTED_TENSORSYMMETRY_FORWARD_H
+#define EIGEN_UNSUPPORTED_TENSORSYMMETRY_FORWARD_H
 
-#include "Tensor"
+#include "../../contrib/Eigen/TensorSymmetry"  // IWYU pragma: export
 
-#include "../../Eigen/src/Core/util/DisableStupidWarnings.h"
-
-/** \defgroup TensorSymmetry_Module Tensor Symmetry Module
- *
- * This module provides a classes that allow for the definition of
- * symmetries w.r.t. tensor indices.
- *
- * Including this module will implicitly include the Tensor module.
- *
- * \code
- * #include <unsupported/Eigen/TensorSymmetry>
- * \endcode
- */
-
-// IWYU pragma: begin_exports
-#include "src/TensorSymmetry/util/TemplateGroupTheory.h"
-#include "src/TensorSymmetry/Symmetry.h"
-#include "src/TensorSymmetry/StaticSymmetry.h"
-#include "src/TensorSymmetry/DynamicSymmetry.h"
-// IWYU pragma: end_exports
-
-#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h"
-
-#endif  // EIGEN_TENSORSYMMETRY_MODULE_H
+#endif  // EIGEN_UNSUPPORTED_TENSORSYMMETRY_FORWARD_H
diff --git a/unsupported/Eigen/ThreadPool b/unsupported/Eigen/ThreadPool
index 4020064..d125502 100644
--- a/unsupported/Eigen/ThreadPool
+++ b/unsupported/Eigen/ThreadPool
@@ -1,5 +1,13 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
 // SPDX-FileCopyrightText: The Eigen Authors
 // SPDX-License-Identifier: MPL-2.0
+//
+// Forwarding header: ThreadPool was promoted to a core Eigen module in
+// Eigen 5.x. New code should use
+//   #include <Eigen/ThreadPool>
+// directly. This shim preserves the legacy include path.
 
 #ifndef EIGEN_UNSUPPORTED_THREADPOOL_FORWARD_H
 #define EIGEN_UNSUPPORTED_THREADPOOL_FORWARD_H
diff --git a/unsupported/Eigen/src/ArpackSupport/InternalHeaderCheck.h b/unsupported/Eigen/src/ArpackSupport/InternalHeaderCheck.h
deleted file mode 100644
index 9e28343..0000000
--- a/unsupported/Eigen/src/ArpackSupport/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_ARPACKSUPPORT_MODULE_H
-#error "Please include unsupported/Eigen/ArpackSupport instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/AutoDiff/InternalHeaderCheck.h b/unsupported/Eigen/src/AutoDiff/InternalHeaderCheck.h
deleted file mode 100644
index 1d8fee9..0000000
--- a/unsupported/Eigen/src/AutoDiff/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_AUTODIFF_MODULE_H
-#error "Please include unsupported/Eigen/AutoDiff instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/BVH/InternalHeaderCheck.h b/unsupported/Eigen/src/BVH/InternalHeaderCheck.h
deleted file mode 100644
index c5c57d7..0000000
--- a/unsupported/Eigen/src/BVH/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_BVH_MODULE_H
-#error "Please include unsupported/Eigen/BVH instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/EulerAngles/InternalHeaderCheck.h b/unsupported/Eigen/src/EulerAngles/InternalHeaderCheck.h
deleted file mode 100644
index 28cad12..0000000
--- a/unsupported/Eigen/src/EulerAngles/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_EULERANGLES_MODULE_H
-#error "Please include unsupported/Eigen/EulerAngles instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/FFT/InternalHeaderCheck.h b/unsupported/Eigen/src/FFT/InternalHeaderCheck.h
deleted file mode 100644
index f61a699..0000000
--- a/unsupported/Eigen/src/FFT/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_FFT_MODULE_H
-#error "Please include unsupported/Eigen/FFT instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/GPU/InternalHeaderCheck.h b/unsupported/Eigen/src/GPU/InternalHeaderCheck.h
deleted file mode 100644
index e94db63..0000000
--- a/unsupported/Eigen/src/GPU/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_GPU_MODULE_H
-#error "Please include unsupported/Eigen/GPU instead of including headers inside the src/GPU directory directly."
-#endif
diff --git a/unsupported/Eigen/src/KroneckerProduct/InternalHeaderCheck.h b/unsupported/Eigen/src/KroneckerProduct/InternalHeaderCheck.h
deleted file mode 100644
index de69b64..0000000
--- a/unsupported/Eigen/src/KroneckerProduct/InternalHeaderCheck.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_KRONECKER_PRODUCT_MODULE_H
-#error \
-    "Please include unsupported/Eigen/KroneckerProduct instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h b/unsupported/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h
deleted file mode 100644
index 6e6f394..0000000
--- a/unsupported/Eigen/src/LevenbergMarquardt/InternalHeaderCheck.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_LEVENBERGMARQUARDT_MODULE_H
-#error \
-    "Please include unsupported/Eigen/LevenbergMarquardt instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/MatrixFunctions/InternalHeaderCheck.h b/unsupported/Eigen/src/MatrixFunctions/InternalHeaderCheck.h
deleted file mode 100644
index 23f0bf9..0000000
--- a/unsupported/Eigen/src/MatrixFunctions/InternalHeaderCheck.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_MATRIX_FUNCTIONS_MODULE_H
-#error \
-    "Please include unsupported/Eigen/MatrixFunctions instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h b/unsupported/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h
deleted file mode 100644
index a26cbe6..0000000
--- a/unsupported/Eigen/src/NonLinearOptimization/InternalHeaderCheck.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_NONLINEAROPTIMIZATION_MODULE_H
-#error \
-    "Please include unsupported/Eigen/NonLinearOptimization instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/NumericalDiff/InternalHeaderCheck.h b/unsupported/Eigen/src/NumericalDiff/InternalHeaderCheck.h
deleted file mode 100644
index 849fa5f..0000000
--- a/unsupported/Eigen/src/NumericalDiff/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_NUMERICALDIFF_MODULE_H
-#error "Please include unsupported/Eigen/NumericalDiff instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/Polynomials/InternalHeaderCheck.h b/unsupported/Eigen/src/Polynomials/InternalHeaderCheck.h
deleted file mode 100644
index 06c0575..0000000
--- a/unsupported/Eigen/src/Polynomials/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_POLYNOMIALS_MODULE_H
-#error "Please include unsupported/Eigen/Polynomials instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/SparseExtra/InternalHeaderCheck.h b/unsupported/Eigen/src/SparseExtra/InternalHeaderCheck.h
deleted file mode 100644
index ededff3..0000000
--- a/unsupported/Eigen/src/SparseExtra/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_SPARSE_EXTRA_MODULE_H
-#error "Please include unsupported/Eigen/SparseExtra instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/SpecialFunctions/InternalHeaderCheck.h b/unsupported/Eigen/src/SpecialFunctions/InternalHeaderCheck.h
deleted file mode 100644
index 823765a..0000000
--- a/unsupported/Eigen/src/SpecialFunctions/InternalHeaderCheck.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_SPECIALFUNCTIONS_MODULE_H
-#error \
-    "Please include unsupported/Eigen/SpecialFunctions instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/Splines/InternalHeaderCheck.h b/unsupported/Eigen/src/Splines/InternalHeaderCheck.h
deleted file mode 100644
index 5124a93..0000000
--- a/unsupported/Eigen/src/Splines/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_SPLINES_MODULE_H
-#error "Please include unsupported/Eigen/Splines instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/StructuredMatrices/InternalHeaderCheck.h b/unsupported/Eigen/src/StructuredMatrices/InternalHeaderCheck.h
deleted file mode 100644
index c51e4b2..0000000
--- a/unsupported/Eigen/src/StructuredMatrices/InternalHeaderCheck.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_STRUCTURED_MATRICES_MODULE_H
-#error \
-    "Please include unsupported/Eigen/StructuredMatrices instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/Tensor/InternalHeaderCheck.h b/unsupported/Eigen/src/Tensor/InternalHeaderCheck.h
deleted file mode 100644
index 80c79ef..0000000
--- a/unsupported/Eigen/src/Tensor/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_TENSOR_MODULE_H
-#error "Please include unsupported/Eigen/Tensor instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/Eigen/src/TensorSymmetry/InternalHeaderCheck.h b/unsupported/Eigen/src/TensorSymmetry/InternalHeaderCheck.h
deleted file mode 100644
index fd713ee..0000000
--- a/unsupported/Eigen/src/TensorSymmetry/InternalHeaderCheck.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-FileCopyrightText: The Eigen Authors
-// SPDX-License-Identifier: MPL-2.0
-
-#ifndef EIGEN_TENSORSYMMETRY_MODULE_H
-#error "Please include unsupported/Eigen/TensorSymmetry instead of including headers inside the src directory directly."
-#endif
diff --git a/unsupported/README.txt b/unsupported/README.txt
deleted file mode 100644
index 70793bf..0000000
--- a/unsupported/README.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-This directory contains contributions from various users.
-They are provided "as is", without any support. Nevertheless,
-most of them are subject to be included in Eigen in the future.
-
-In order to use an unsupported module you have to do either:
-
- - add the path_to_eigen/unsupported directory to your include path and do:
-   #include <Eigen/ModuleHeader>
-
- - or directly do:
-   #include <unsupported/Eigen/ModuleHeader>
-
-
-If you are interested in contributing to one of them, or have other stuff
-you would like to share, feel free to contact us:
-http://eigen.tuxfamily.org/index.php?title=Main_Page#Mailing_list
-
-Any kind of contributions are much appreciated, even very preliminary ones.
-However, it:
- - must rely on Eigen,
- - must be highly related to math,
- - should have some general purpose in the sense that it could
-   potentially become an official Eigen module (or be merged into another one).
-
-In doubt feel free to contact us. For instance, if your addons is very too specific
-but it shows an interesting way of using Eigen, then it could be a nice demo.
-
-
-This directory is organized as follow:
-
-unsupported/Eigen/ModuleHeader1
-unsupported/Eigen/ModuleHeader2
-unsupported/Eigen/...
-unsupported/Eigen/src/Module1/SourceFile1.h
-unsupported/Eigen/src/Module1/SourceFile2.h
-unsupported/Eigen/src/Module1/...
-unsupported/Eigen/src/Module2/SourceFile1.h
-unsupported/Eigen/src/Module2/SourceFile2.h
-unsupported/Eigen/src/Module2/...
-unsupported/Eigen/src/...
-unsupported/doc/snippets/.cpp   <- code snippets for the doc
-unsupported/doc/examples/.cpp   <- examples for the doc
-unsupported/doc/TutorialModule1.dox
-unsupported/doc/TutorialModule2.dox
-unsupported/doc/...
-unsupported/test/.cpp           <- unit test files
-
-The documentation is generated at the same time than the main Eigen documentation.
-The .html files are generated in: build_dir/doc/html/unsupported/
-