Skip to content

ENH: Deprecate the vnl_svd family for the Eigen-backed itk::Math::SVD#6564

Open
hjmjohnson wants to merge 4 commits into
InsightSoftwareConsortium:mainfrom
hjmjohnson:enh-deprecate-vnl-svd-family
Open

ENH: Deprecate the vnl_svd family for the Eigen-backed itk::Math::SVD#6564
hjmjohnson wants to merge 4 commits into
InsightSoftwareConsortium:mainfrom
hjmjohnson:enh-deprecate-vnl-svd-family

Conversation

@hjmjohnson

@hjmjohnson hjmjohnson commented Jul 8, 2026

Copy link
Copy Markdown
Member

Deprecates the vnl_svd family (vnl_svd, vnl_svd_fixed, vnl_svd_economy, vnl_matrix_inverse) in favor of the Eigen-backed itk::Math::SVD, migrates every in-tree consumer, and build-gates the LINPACK svdc engine out of ITK_FUTURE_LEGACY_REMOVE. The itk::Math::SolveSymmetric/InverseSymmetric (LDLT) work that previously lived here is split out to #6565 so the two review independently.

Commit structure (4 thematic commits)
  1. Extend itk::Math::SVD — pseudo-inverse, solve, rank, recompose, null-vector, WellCondition, DeterminantMagnitude; eigenvector sign routed through itkEigenDecompositionSignConvention for backend-stable results.
  2. Test the extended surface against vnl_svd on well- and ill-conditioned inputs.
  3. Migrate consumers (transforms, DTI reconstruction, image moments, label-map, membership functions, Mahalanobis metrics, Quasi-Newton optimizer, NIfTI/MINC IO, classifier estimators, itk::Matrix::GetInverse). Widely-included headers keep the transitive vnl_svd* include reachable under #if !defined(ITK_LEGACY_REMOVE) && !defined(ITK_FUTURE_LEGACY_REMOVE) so downstream code that relied on it still compiles during the deprecation window.
  4. Deprecate the vnl_svd family with the three-state guard (silent default / #warning under ITK_LEGACY_REMOVE / #error under ITK_FUTURE_LEGACY_REMOVE) and build-gate the LINPACK svdc sources.
Downstream validation (forest)

Built against this branch's tip in the ITK downstream forest: ITK, ANTs, BRAINSTools, c3d, SimpleITK all compile clean. The one real regression found — ANTs antsAffineInitializer relying on a transitive vnl_svd_fixed.h via itkTransform.hxx — is fixed by the guarded transitive includes in commit 3. No consumer hit any vnl_svd/vnl_matrix_inverse/itk::Math::SVD compile error. (c3d and SimpleITK additionally needed their own upstream ITK6-migration PRs, unrelated to this change.)

@github-actions github-actions Bot added type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Enhancement Improvement of existing methods or implementation type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module area:Filtering Issues affecting the Filtering module area:IO Issues affecting the IO module area:Registration Issues affecting the Registration module area:Segmentation Issues affecting the Segmentation module area:ThirdParty Issues affecting the ThirdParty module area:Numerics Issues affecting the Numerics module labels Jul 8, 2026
@hjmjohnson hjmjohnson changed the title ENH: Deprecate the vnl_svd SVD family in favour of itk::Math::SVD ENH: Deprecate the vnl_svd SVD family, and add itk::Math::SolveSymmetric (Eigen LDLT) Jul 8, 2026
@hjmjohnson

hjmjohnson commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Scope update (superseded): the itk::Math::SolveSymmetric / InverseSymmetric (Eigen LDLT) work has been split out to #6565. This PR is now the vnl_svd-family deprecation only (vnl_svd, vnl_svd_fixed, vnl_svd_economy, vnl_matrix_inverseitk::Math::SVD).

@hjmjohnson hjmjohnson force-pushed the enh-deprecate-vnl-svd-family branch 2 times, most recently from 6707e4c to 76036f9 Compare July 8, 2026 12:32
@hjmjohnson hjmjohnson force-pushed the enh-deprecate-vnl-svd-family branch from 76036f9 to 619512b Compare July 8, 2026 17:22
@hjmjohnson hjmjohnson changed the title ENH: Deprecate the vnl_svd SVD family, and add itk::Math::SolveSymmetric (Eigen LDLT) ENH: Deprecate the vnl_svd family for the Eigen-backed itk::Math::SVD Jul 8, 2026
@hjmjohnson hjmjohnson force-pushed the enh-deprecate-vnl-svd-family branch from 619512b to 520c2f2 Compare July 8, 2026 23:57
@hjmjohnson hjmjohnson marked this pull request as ready for review July 9, 2026 00:54
@greptile-apps

This comment was marked as resolved.

Comment thread Modules/Registration/Common/test/RegistrationITKv3/ImageRegistration9.cxx Outdated
Extend the Eigen-backed itk::Math::SVD helpers so every vnl_svd /
vnl_matrix_inverse call site in ITK has a direct replacement: pseudo-inverse,
solve, rank, recompose, null vector, and the WellCondition and
DeterminantMagnitude predicates. Route the eigenvector sign convention through
itkEigenDecompositionSignConvention so results are backend-stable.
Exercise the extended itk::Math::SVD surface (pseudo-inverse, solve, rank,
WellCondition, DeterminantMagnitude) and cross-check it against the vnl_svd
result on well- and ill-conditioned inputs.
@hjmjohnson hjmjohnson force-pushed the enh-deprecate-vnl-svd-family branch from 520c2f2 to 7c01e6f Compare July 9, 2026 02:24
…h::SVD

Replace direct vnl_svd, vnl_svd_fixed and vnl_matrix_inverse use across the
transforms, diffusion-tensor reconstruction, image moments, label-map filters,
membership functions, Mahalanobis metrics, the Quasi-Newton optimizer, NIfTI
and MINC IO and the classifier estimators with the Eigen-backed itk::Math::SVD
API, including itk::Matrix::GetInverse.

Where a widely included header (itkTransform, itkMatrix, the affine transforms)
previously pulled a vnl_svd* header transitively, keep that include reachable
under
  #if !defined(ITK_LEGACY_REMOVE) && !defined(ITK_FUTURE_LEGACY_REMOVE)
so downstream code that relied on the transitive include still compiles during
the deprecation window.
Add the three-state deprecation guard to vnl_svd, vnl_svd_fixed,
vnl_svd_economy, vnl_matrix_inverse and vnl_solve_qp, pointing callers at the
Eigen-backed itk::Math::SVD: silent by default, a #warning under
ITK_LEGACY_REMOVE and a hard #error under ITK_FUTURE_LEGACY_REMOVE.

Build-gate the vnl_svd family and the LINPACK svdc netlib sources out of the
ITK_FUTURE_LEGACY_REMOVE build so the dead engine no longer compiles once the
APIs are gone, and move the vnl algo tests off the deprecated spellings.
@hjmjohnson hjmjohnson force-pushed the enh-deprecate-vnl-svd-family branch from 7c01e6f to 232a2ad Compare July 9, 2026 12:05
@github-actions github-actions Bot added the area:Examples Demonstration of the use of classes label Jul 9, 2026
@hjmjohnson

Copy link
Copy Markdown
Member Author

Fixed the ITK.Linux (LegacyRemovedDebugCxx20) failure in 232a2adExamples/RegistrationITKv4/ImageRegistration9.cxx still used vnl_svd<double> via a transitive include that this PR guards out under ITK_LEGACY_REMOVE. Migrated it to itk::Math::SVD (svd.U * svd.V.transpose()), matching the sibling test/RegistrationITKv3 example. A full-tree sweep confirms no other vnl_svd/vnl_matrix_inverse consumers remain outside the vendored VNL sources. Builds clean locally.

@blowekamp

Copy link
Copy Markdown
Member

Is the recommendation moving forward going to be to directly use Eigen or use new ITK interfaces?

@hjmjohnson

Copy link
Copy Markdown
Member Author

Is the recommendation moving forward going to be to directly use Eigen or use new ITK interfaces?

I would say to use the ITK interfaces. A few (or perhaps many now) years ago, at a NA-MIC meeting, several people were lamenting the fact that VXL was exposed to end-users as part of the ITK API, and how that decision both increased the maintenance burden and limited how we could improve ITK. I am trying to avoid that trap with Eigen.

Internally, we can use Eigen directly, but we should provide an ITK API wrapper that does not expose Eigen to consumers of ITK. This will allow future algorithmic changes to be made independent of what Eigen does.

Judicious use of itk::Math::detail namespaces where Eigen interfaces provide performance benefits are used to indicate that, while they are part of the 'technical' public API, conceptually we do not consider them part of the public API, and we do not make any guarantees about backward compatibility for those details.

@blowekamp

Copy link
Copy Markdown
Member

everal people were lamenting the fact that VXL was exposed to end-users as part of the ITK API, and how that decision both increased the maintenance burden and limited how we could improve ITK. I am trying to avoid that trap with Eigen.

I had thought that comment referenced the classes that were derived from VNL object, along with the the operator that operated on VNL objects.

@hjmjohnson

Copy link
Copy Markdown
Member Author

everal people were lamenting the fact that VXL was exposed to end-users as part of the ITK API, and how that decision both increased the maintenance burden and limited how we could improve ITK. I am trying to avoid that trap with Eigen.

I had thought that comment referenced the classes that were derived from VNL object, along with the the operator that operated on VNL objects.

@blowekamp Do you see this as a step in the wrong direction, or are you concerned about the approach? I'd like to understand your view on the correct approach. Do you think a Zoom call would help?

My approach/motivation: I was trying to replace vnl_ (backed by pre-1999 FORTRAN) -> itk::Math:: (backed by Eigen). In most cases, this provides 2 wins: 1) Performance (limited at the moment, Eigen unlocks other performance improvements that will need to be revisited later), and 2) Almost always better numerical accuracy. Also, Eigen is having a huge (Nvidia-backed) engineering modernization effort going on right now that will hopefully filter into ITK for free.

@hjmjohnson hjmjohnson requested a review from thewtex July 10, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Core Issues affecting the Core module area:Examples Demonstration of the use of classes area:Filtering Issues affecting the Filtering module area:IO Issues affecting the IO module area:Numerics Issues affecting the Numerics module area:Registration Issues affecting the Registration module area:Segmentation Issues affecting the Segmentation module area:ThirdParty Issues affecting the ThirdParty module type:Enhancement Improvement of existing methods or implementation type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants