fix(#182): linear-algebra API was unconstructible and SVD returned wrong results - #195
Merged
Merged
Conversation
…ed wrong results) The reporter moved on to SVD and found the documented linear-algebra API unusable. Every one of their observations was a real defect: 1. GPULinearAlgebraProvider was IMPOSSIBLE TO CONSTRUCT. Its constructor required an IKernelManager — an interface with no implementation anywhere in the repo — so the README's headline example could never compile. Worse, AddDotComputeAlgorithms() registered GpuMatrixOperations, which had the same required dependency, so that registration could not be resolved either. IKernelManager is now optional on both (it is only needed for custom GPU kernel execution); the GPU kernel paths raise a descriptive error which the provider already catches to fall back to CPU. Both types are now registered via factories that resolve IKernelManager optionally. 2. SVD RETURNED MATHEMATICALLY WRONG RESULTS. GpuMatrixOperations.SVDAsync and GpuOptimizationStrategies.FallbackSVDAsync each carried their own "simplified eigendecomposition of A^T*A" (its own comment: "not numerically stable"). On a 6x6 matrix it produced unsorted singular values (0.6724, 0.0517, 0.4761 vs the true 4.6418, 3.2217, 2.8212) and a factorization that did not reconstruct the input at all (|U*S*V^T - A| = 2.8). Both now delegate to the existing, correct one-sided Jacobi SVD (MatrixDecomposition.ComputeJacobiSVD), so every entry point shares one implementation. 3. The README documented APIs that do not exist: IAcceleratorService (no such type), LinearAlgebraKernels.GetKernelSource (the type is LinearAlgebraKernelLibrary), AdvancedLinearAlgebraKernels (no such file/type), and GetOptimizedParameters (internal). The usage sections are rewritten against the current build and now also answer the reporter's actual question — how to obtain an IAccelerator (from DI; a kernel name is only needed for IComputeOrchestrator, which runs user [Kernel] methods). Verified: provider SVD reconstruction 1.7e-6 (was 2.8), Multiply 1.2e-7, QR 3.0e-8, Solve 5.6e-8; provider and MatrixMath now agree. New regression tests cover constructibility, DI resolution, SVD reconstruction, descending singular values, and provider/MatrixMath agreement. 262 Algorithms tests pass; solution builds clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Round 8 of #182. The reporter fixed their N-body data race, moved on to SVD, and found the linear-algebra API unusable. Every observation was a real defect — including one that silently returned wrong math.
1.
GPULinearAlgebraProviderwas impossible to constructIts constructor required an
IKernelManager— an interface with no implementation anywhere in the repo — so the README's headline example could never compile. Worse,AddDotComputeAlgorithms()registeredGpuMatrixOperations, which had the same required dependency, so that registration could not be resolved either.IKernelManageris now optional on both (it is only needed for custom GPU kernel execution). The two GPU kernel call sites raise a descriptive error, which the provider already catches to fall back to CPU. Both types are registered via factories that resolveIKernelManageroptionally.2. SVD returned mathematically wrong results 🔴
GpuMatrixOperations.SVDAsyncandGpuOptimizationStrategies.FallbackSVDAsynceach carried their own "simplified eigendecomposition of A^T·A" — its own comment admitted "not numerically stable". On a 6×6 matrix:0.6724, 0.0517, 0.4761(unsorted, wrong)4.6418, 3.2217, 2.8212Both now delegate to the existing, correct one-sided Jacobi SVD (
MatrixDecomposition.ComputeJacobiSVD), so every entry point shares one implementation.MatrixMath.SVDAsyncwas already correct — the two now agree.3. The README documented APIs that do not exist
IAcceleratorService— no such type anywhere.LinearAlgebraKernels.GetKernelSource— the type isLinearAlgebraKernelLibrary.AdvancedLinearAlgebraKernels— no such file or type.GetOptimizedParameters—internal, not usable.Usage sections rewritten against the current build, and they now answer the reporter's actual question: how to get an
IAccelerator(from DI — a kernel name is only needed forIComputeOrchestrator, which runs user[Kernel]methods).Verification
Everything documented was executed first: provider SVD reconstruction 1.7e-6, Multiply 1.2e-7, QR 3.0e-8, Solve 5.6e-8, and provider ≡
MatrixMath. New regression tests cover constructibility, DI resolution, SVD reconstruction, descending singular values, and provider/MatrixMath agreement. 262 Algorithms tests pass; solution builds clean.Known remaining inconsistency (not addressed here)
The reporter also noticed duplication, and they're right: there are two
Matrixclasses (…LinearAlgebra.Matrixand…Types.LinearAlgebra.Matrix) and twoLinearAlgebraOperationenums (…Algorithmsand…Types). Consolidating those is a public-API breaking change and deserves its own issue rather than being bundled into a bug fix.🤖 Generated with Claude Code