26#ifndef math_svdDowndate_hpp
27#define math_svdDowndate_hpp
44#if defined( __GNUC__ ) || defined( __clang__ )
45#define MXLIB_SVD_DELETION_HEADER_ADAPTER inline __attribute__( ( visibility( "hidden" ) ) )
47#define MXLIB_SVD_DELETION_HEADER_ADAPTER inline
90template <
typename realT>
91using svdDeletionMatrix = Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
94template <
typename realT>
98template <
typename realT>
102template <
typename realT>
105static_assert( std::is_integral_v<Eigen::Index>,
"The SVD-deletion ABI requires Eigen::Index to be an integral type." );
106static_assert( std::is_signed_v<Eigen::Index>,
"The SVD-deletion ABI requires Eigen::Index to be signed." );
107static_assert(
sizeof( Eigen::Index ) <=
sizeof( std::int64_t ),
108 "The SVD-deletion ABI cannot represent an Eigen::Index wider than int64_t." );
109static_assert(
sizeof( Eigen::Index ) ==
sizeof( std::ptrdiff_t ),
110 "The SVD-deletion ABI requires Eigen::Index and ptrdiff_t to have the same width." );
113template <
typename realT>
122template <
typename realT>
144static_assert( std::is_standard_layout_v<svdDeletionConstVectorViewV2<float>> );
145static_assert( std::is_trivially_copyable_v<svdDeletionConstVectorViewV2<float>> );
146static_assert( std::is_standard_layout_v<svdDeletionConstVectorViewV2<double>> );
147static_assert( std::is_trivially_copyable_v<svdDeletionConstVectorViewV2<double>> );
148static_assert( std::is_standard_layout_v<svdDeletionConstMatrixViewV2<float>> );
149static_assert( std::is_trivially_copyable_v<svdDeletionConstMatrixViewV2<float>> );
150static_assert( std::is_standard_layout_v<svdDeletionConstMatrixViewV2<double>> );
151static_assert( std::is_trivially_copyable_v<svdDeletionConstMatrixViewV2<double>> );
152static_assert( std::is_standard_layout_v<svdDeletionConstIndexViewV2> );
153static_assert( std::is_trivially_copyable_v<svdDeletionConstIndexViewV2> );
160template <
typename realT,
typename abiT = svdDeletionAbiV2Tag>
163template <
typename realT,
typename abiT = svdDeletionAbiV2Tag>
169template <
typename realT>
170struct svdDeletionImplementation;
181template <
typename realT>
185 std::int64_t outputRank,
189template <
typename realT>
193 std::int64_t outputRank,
197template <
typename realT>
201 std::int64_t outputRank,
206template <
typename realT>
211 std::int64_t outputRank,
216template <
typename realT>
221 std::int64_t outputRank,
230enum class svdDeletionTestOperation
238using svdDeletionOperationHookT = void ( * )( svdDeletionTestOperation );
241template <
typename realT>
242using svdDeletionSyevrHookT = MXLAPACK_INT ( * )( char,
264template <
typename realT>
265using svdDeletionGesvdHookT = MXLAPACK_INT ( * )( char,
280template <
typename realT>
281using svdDeletionLaed9HookT =
282 MXLAPACK_INT ( * )( realT *, realT *, realT *, MXLAPACK_INT, MXLAPACK_INT, realT, realT *, realT * );
285template <
typename realT>
286struct svdDeletionTestHooks
289 svdDeletionOperationHookT operation{
nullptr };
292 svdDeletionSyevrHookT<realT> syevr{
nullptr };
295 svdDeletionGesvdHookT<realT>
gesvd{
nullptr };
298 svdDeletionLaed9HookT<realT>
laed9{
nullptr };
302template <
typename realT>
303svdDeletionTestHooks<realT> &svdDeletionHooks();
320template <
typename realT,
typename abiT>
323 static_assert( std::is_same_v<abiT, svdDeletionAbiV2Tag>,
324 "svdDeletionResult does not support a caller-selected ABI tag." );
350 MXLIB_SVD_DELETION_HEADER_ADAPTER
354 return prepareAbiV2(
static_cast<std::int64_t
>(
baseRank ),
static_cast<std::int64_t
>(
outputRank ) );
368 return Eigen::Map<const svdDeletionVector<realT>, Eigen::Unaligned>( view.
data,
369 static_cast<Eigen::Index
>( view.
size ) );
377 return Eigen::Map<const svdDeletionVector<realT>, Eigen::Unaligned>( view.
data,
378 static_cast<Eigen::Index
>( view.
size ) );
386 using mapT = Eigen::Map<const svdDeletionMatrix<realT>, Eigen::Unaligned, Eigen::OuterStride<Eigen::Dynamic>>;
387 return mapT( view.
data,
388 static_cast<Eigen::Index
>( view.
rows ),
389 static_cast<Eigen::Index
>( view.
columns ),
390 Eigen::OuterStride<Eigen::Dynamic>(
static_cast<Eigen::Index
>( view.
outerStride ) ) );
415 friend struct detail::svdDeletionImplementation<realT>;
431 bool ensureStorage() noexcept;
436 std::unique_ptr<storage> m_storage;
447template <typename realT, typename abiT>
450 static_assert( std::is_same_v<abiT, svdDeletionAbiV2Tag>,
451 "svdDeletionWorkspace does not support a caller-selected ABI tag." );
475 MXLIB_SVD_DELETION_HEADER_ADAPTER
480 return prepareAbiV2(
static_cast<std::int64_t
>(
baseRank ),
504 friend struct detail::svdDeletionImplementation<realT>;
512 bool ensureStorage() noexcept;
517 std::unique_ptr<storage> m_storage;
526 float tolerance = 0 )
528 return detail::validateSvdDeletionFactorAbiV2( { factor.data(),
529 static_cast<std::int64_t
>( factor.rows() ),
530 static_cast<std::int64_t
>( factor.cols() ),
531 static_cast<std::int64_t
>( factor.outerStride() ) },
538 double tolerance = 0 )
540 return detail::validateSvdDeletionFactorAbiV2( { factor.data(),
541 static_cast<std::int64_t
>( factor.rows() ),
542 static_cast<std::int64_t
>( factor.cols() ),
543 static_cast<std::int64_t
>( factor.outerStride() ) },
559template <
typename realT>
567 return detail::svdDeletionLeadingCoreAbiV2<realT>(
570 { deletedRows.data(),
571 static_cast<std::int64_t
>( deletedRows.rows() ),
572 static_cast<std::int64_t
>( deletedRows.cols() ),
573 static_cast<std::int64_t
>( deletedRows.outerStride() ) },
593template <
typename realT>
601 return detail::svdDeletionStableCoreAbiV2<realT>(
604 { deletedRows.data(),
605 static_cast<std::int64_t
>( deletedRows.rows() ),
606 static_cast<std::int64_t
>( deletedRows.cols() ),
607 static_cast<std::int64_t
>( deletedRows.outerStride() ) },
619template <
typename realT>
628 return detail::svdDeletionCoreAbiV2<realT>(
631 { deletedRows.data(),
632 static_cast<std::int64_t
>( deletedRows.rows() ),
633 static_cast<std::int64_t
>( deletedRows.cols() ),
634 static_cast<std::int64_t
>( deletedRows.outerStride() ) },
645template <
typename realT>
650 std::span<const Eigen::Index> deletedIndices,
655 return detail::svdRemoveRowsAbiV2<realT>(
659 static_cast<std::int64_t
>( leftFactor.rows() ),
660 static_cast<std::int64_t
>( leftFactor.cols() ),
661 static_cast<std::int64_t
>( leftFactor.outerStride() ) },
662 { deletedIndices.data(),
663 static_cast<std::int64_t
>( deletedIndices.size() ),
664 static_cast<std::int64_t
>(
sizeof( Eigen::Index ) ) },
675template <
typename realT>
680 std::span<const Eigen::Index> deletedIndices,
685 return detail::svdRemoveColumnsAbiV2<realT>(
688 { rightFactor.data(),
689 static_cast<std::int64_t
>( rightFactor.rows() ),
690 static_cast<std::int64_t
>( rightFactor.cols() ),
691 static_cast<std::int64_t
>( rightFactor.outerStride() ) },
692 { deletedIndices.data(),
693 static_cast<std::int64_t
>( deletedIndices.size() ),
694 static_cast<std::int64_t
>(
sizeof( Eigen::Index ) ) },
702#undef MXLIB_SVD_DELETION_HEADER_ADAPTER
Result of deleting rows or columns from a represented thin SVD.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus prepare(Eigen::Index baseRank, Eigen::Index outputRank)
Prepare or reuse output storage for a base and requested active output rank.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionConstMatrixRef< realT > rotation() const noexcept
Return the preserved-side rotation, with updated directions in columns.
svdDeletionResult & operator=(svdDeletionResult &&other) noexcept
Replace this result by moving owned storage from another result.
svdDeletionResult & operator=(const svdDeletionResult &other)=delete
Results cannot be copy-assigned across the mxlib ABI boundary.
svdDeletionStatus status() const noexcept
Return the most recent operation status.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionConstVectorRef< realT > singularValues() const noexcept
realT minimumPSDValue() const noexcept
svdDeletionResult()
Construct an empty result.
std::int64_t clampedEigenvalues() const noexcept
std::int64_t outputRank() const noexcept
std::int64_t maximumOutputRank() const noexcept
~svdDeletionResult()
Release result storage using mxlib's Eigen allocation configuration.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionConstVectorRef< realT > squaredSingularValues() const noexcept
Return an unaligned borrowed view of all corresponding descending squared singular values.
std::int64_t baseRank() const noexcept
MXLAPACK_INT lapackInfo() const noexcept
svdDeletionResult(const svdDeletionResult &other)=delete
Results cannot be copied across the mxlib ABI boundary.
svdDeletionBackend backend() const noexcept
svdDeletionResult(svdDeletionResult &&other) noexcept
Move owned result storage from another result.
Reusable, non-shared storage for SVD deletion operations.
bool prepared() const noexcept
svdDeletionWorkspace()
Construct an empty workspace.
MXLAPACK_INT lapackInfo() const noexcept
void clear() noexcept
Release all prepared storage and reset dimensions.
std::int64_t baseRank() const noexcept
svdDeletionBackend backend() const noexcept
svdDeletionWorkspace & operator=(svdDeletionWorkspace &&other) noexcept
Replace this workspace by moving owned storage and preparation state.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus prepare(Eigen::Index baseRank, Eigen::Index maximumDeleted, svdDeletionBackend backend)
Prepare reusable storage and LAPACK work arrays.
svdDeletionWorkspace(const svdDeletionWorkspace &other)=delete
Workspaces cannot be copied.
std::int64_t maximumDeleted() const noexcept
svdDeletionWorkspace(svdDeletionWorkspace &&other) noexcept
Move owned storage and preparation state from another workspace.
~svdDeletionWorkspace()
Release owned scratch storage.
svdDeletionWorkspace & operator=(const svdDeletionWorkspace &other)=delete
Workspaces cannot be copy-assigned.
const char * svdDeletionStatusName(svdDeletionStatus status)
Return a stable text representation of an SVD deletion status.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus svdDeletionCore(svdDeletionResult< realT > &result, std::type_identity_t< svdDeletionConstVectorRef< realT > > singularValues, std::type_identity_t< svdDeletionConstMatrixRef< realT > > deletedRows, Eigen::Index outputRank, svdDeletionWorkspace< realT > &workspace, svdDeletionBackend backend=svdDeletionBackend::stableCore)
Delete supplied singular-factor rows with an explicitly selected backend.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus svdRemoveColumns(svdDeletionResult< realT > &result, std::type_identity_t< svdDeletionConstVectorRef< realT > > singularValues, std::type_identity_t< svdDeletionConstMatrixRef< realT > > rightFactor, std::span< const Eigen::Index > deletedIndices, Eigen::Index outputRank, svdDeletionWorkspace< realT > &workspace, svdDeletionBackend backend=svdDeletionBackend::stableCore)
Delete physical columns from the matrix represented by a thin SVD.
svdDeletionStatus
Completion status for an SVD deletion operation.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus validateSvdDeletionFactor(svdDeletionConstMatrixRef< float > factor, float tolerance=0)
Validate that a supplied thin singular-vector factor has orthonormal columns.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus svdDeletionLeadingCore(svdDeletionResult< realT > &result, std::type_identity_t< svdDeletionConstVectorRef< realT > > singularValues, std::type_identity_t< svdDeletionConstMatrixRef< realT > > deletedRows, Eigen::Index outputRank, svdDeletionWorkspace< realT > &workspace)
Delete supplied singular-factor rows with the full-spectrum symmetric covariance core.
svdDeletionBackend
Numerical backend used to delete rows or columns from thin-SVD factors.
Eigen::Array< realT, Eigen::Dynamic, 1 > svdDeletionVector
Dynamic column vector used by the SVD deletion API.
const char * svdDeletionBackendName(svdDeletionBackend backend)
Return a stable text representation of an SVD deletion backend.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus svdRemoveRows(svdDeletionResult< realT > &result, std::type_identity_t< svdDeletionConstVectorRef< realT > > singularValues, std::type_identity_t< svdDeletionConstMatrixRef< realT > > leftFactor, std::span< const Eigen::Index > deletedIndices, Eigen::Index outputRank, svdDeletionWorkspace< realT > &workspace, svdDeletionBackend backend=svdDeletionBackend::stableCore)
Delete physical rows from the matrix represented by a thin SVD.
MXLIB_SVD_DELETION_HEADER_ADAPTER svdDeletionStatus svdDeletionStableCore(svdDeletionResult< realT > &result, std::type_identity_t< svdDeletionConstVectorRef< realT > > singularValues, std::type_identity_t< svdDeletionConstMatrixRef< realT > > deletedRows, Eigen::Index outputRank, svdDeletionWorkspace< realT > &workspace)
Delete supplied singular-factor rows with the complement-preserving small-SVD core.
Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > svdDeletionMatrix
Column-major dynamic matrix used by the SVD deletion API.
bool svdDeletionSucceeded(svdDeletionStatus status) noexcept
Return true when a status represents usable numerical output.
Eigen::Ref< const svdDeletionVector< realT > > svdDeletionConstVectorRef
Non-owning read-only reference to a compatible SVD deletion vector.
Eigen::Ref< const svdDeletionMatrix< realT > > svdDeletionConstMatrixRef
Non-owning read-only reference to a compatible column-major SVD deletion matrix.
@ unsupportedDeletionCount
The selected backend cannot process the requested number of deleted rows.
@ success
The operation completed without numerical clamping.
@ rescalingOverflow
A finite normalized result cannot be represented after restoring input scale.
@ nonFiniteOutput
LAPACK returned a non-finite singular system.
@ notComputed
No operation has published a result.
@ invalidInput
Dimensions, values, indices, or requested output rank are invalid.
@ factorNotOrthonormal
A requested singular-factor validation failed.
@ nonPositiveSemidefinite
A theoretically PSD core has a materially negative eigenvalue.
@ successWithClamping
The operation completed after clamping roundoff-scale negative eigenvalues.
@ allocationFailure
Result or workspace allocation failed.
@ workspaceQueryFailure
LAPACK returned an invalid or failed workspace query.
@ invalidSolverOutput
LAPACK returned a finite spectrum with invalid ordering or sign.
@ solverFailure
LAPACK failed during the numerical solve.
@ stableCore
Complement-preserving small SVD; avoids squaring singular-value conditioning.
@ leadingCovariance
Symmetric leading-spectrum core; fastest when small singular values are not required.
@ rankOneSecular
Structured covariance eigensolve for deleting exactly one singular-factor row.
MXLAPACK_INT gesvd(char JOBU, char JOBVT, MXLAPACK_INT M, MXLAPACK_INT N, dataT *A, MXLAPACK_INT LDA, dataT *S, dataT *U, MXLAPACK_INT LDU, dataT *VT, MXLAPACK_INT LDVT, dataT *WORK, MXLAPACK_INT LWORK)
Compute the singular value decomposition (SVD) of a real matrix.
MXLAPACK_INT laed9(dataT *D, dataT *Q, dataT *S, MXLAPACK_INT K, MXLAPACK_INT KSTART, MXLAPACK_INT KSTOP, MXLAPACK_INT N, MXLAPACK_INT LDQ, dataT RHO, dataT *DLAMDA, dataT *W, MXLAPACK_INT LDS)
Solve selected roots of a diagonal-plus-rank-one secular equation and form its eigenvectors.
Type-level ABI tag for the second-generation opaque SVD deletion handles.
ABI-stable borrowed signed-index storage descriptor.
std::int64_t elementBytes
Width of each signed integer element.
std::int64_t size
Number of indices.
const void * data
First signed index, or null for an empty view.
ABI-stable borrowed column-major matrix storage descriptor.
const realT * data
First scalar, or null for an empty view.
std::int64_t outerStride
Scalar stride between successive columns.
std::int64_t columns
Matrix column count.
std::int64_t rows
Matrix row count.
ABI-stable borrowed contiguous-vector storage descriptor.
const realT * data
First scalar, or null for an empty view.
std::int64_t size
Number of contiguous scalars.
Declares and defines templatized wrappers for the Lapack library.