From 582a491c7d4d00c755fb9f66fff9b4b1471b989b Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Fri, 13 Feb 2026 15:10:27 +0100 Subject: [PATCH 1/3] Replace deprecated libtorch APIs with torch::linalg equivalents - THSTensor_cholesky: Replace tensor->cholesky(upper) with torch::linalg_cholesky, using .mH() for upper-triangular results - THSTensor_lu_solve: Replace tensor->lu_solve() with torch::linalg_lu_solve - Fix THSLinalg_lu_solve naming bug (was incorrectly named THSTensor_lu_solve) - Add [Obsolete] attributes to C# wrappers for cholesky() and lu_solve() - Update tests to use linalg.lu_solve instead of deprecated lu_solve --- src/Native/LibTorchSharp/THSLinearAlgebra.cpp | 10 +++++++--- src/TorchSharp/Tensor/Tensor.LinearAlgebra.cs | 1 + src/TorchSharp/Tensor/torch.BlasAndLapackOperations.cs | 4 ++++ src/TorchSharp/Tensor/torch.cs | 3 +++ test/TorchSharpTest/LinearAlgebra.cs | 4 ++-- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Native/LibTorchSharp/THSLinearAlgebra.cpp b/src/Native/LibTorchSharp/THSLinearAlgebra.cpp index 202d3de47..8a3e747b6 100644 --- a/src/Native/LibTorchSharp/THSLinearAlgebra.cpp +++ b/src/Native/LibTorchSharp/THSLinearAlgebra.cpp @@ -351,14 +351,16 @@ Tensor THSLinalg_vecdot(const Tensor x, const Tensor y, const int64_t dim, Tenso CATCH_TENSOR(out == nullptr ? torch::linalg_vecdot(* x, *y, dim) : torch::linalg_vecdot_out(*out, *x, *y, dim)) } -Tensor THSTensor_lu_solve(const Tensor B, const Tensor LU, const Tensor pivots, bool left, bool adjoint, Tensor out) +Tensor THSLinalg_lu_solve(const Tensor B, const Tensor LU, const Tensor pivots, bool left, bool adjoint, Tensor out) { CATCH_TENSOR(out == nullptr ? torch::linalg_lu_solve(*LU, *pivots, *B, left, adjoint) : torch::linalg_lu_solve_out(*out, *LU, *pivots, *B, left, adjoint)) } Tensor THSTensor_cholesky(const Tensor tensor, const bool upper) { - CATCH_TENSOR(tensor->cholesky(upper)) + // torch::cholesky is deprecated in favor of torch::linalg_cholesky. + // linalg_cholesky always returns lower-triangular; use .mH() for upper. + CATCH_TENSOR(upper ? torch::linalg_cholesky(*tensor).mH() : torch::linalg_cholesky(*tensor)) } Tensor THSTensor_cholesky_inverse(const Tensor tensor, const bool upper) @@ -441,7 +443,9 @@ Tensor THSTensor_lu(const Tensor tensor, bool pivot, bool get_infos, Tensor* inf Tensor THSTensor_lu_solve(const Tensor tensor, const Tensor LU_data, const Tensor LU_pivots) { - CATCH_TENSOR(tensor->lu_solve(*LU_data, *LU_pivots)) + // tensor.lu_solve is deprecated in favor of torch::linalg_lu_solve. + // Note: linalg_lu_solve arg order is (LU, pivots, B). + CATCH_TENSOR(torch::linalg_lu_solve(*LU_data, *LU_pivots, *tensor)) } Tensor THSTensor_lu_unpack(const Tensor LU_data, const Tensor LU_pivots, bool unpack_data, bool unpack_pivots, Tensor* L, Tensor* U) diff --git a/src/TorchSharp/Tensor/Tensor.LinearAlgebra.cs b/src/TorchSharp/Tensor/Tensor.LinearAlgebra.cs index 53e6facfb..01d6be280 100644 --- a/src/TorchSharp/Tensor/Tensor.LinearAlgebra.cs +++ b/src/TorchSharp/Tensor/Tensor.LinearAlgebra.cs @@ -64,6 +64,7 @@ public Tensor tensordot(Tensor b, long dims = 2) /// /// If upper is true, the returned matrix U is upper-triangular. If upper is false, the returned matrix L is lower-triangular /// + [Obsolete("torch.cholesky is deprecated in favor of torch.linalg.cholesky and will be removed in a future release. Use torch.linalg.cholesky instead.", false)] public Tensor cholesky(bool upper = false) { var res = THSTensor_cholesky(Handle, upper); diff --git a/src/TorchSharp/Tensor/torch.BlasAndLapackOperations.cs b/src/TorchSharp/Tensor/torch.BlasAndLapackOperations.cs index ff6f4d6b1..5215e4544 100644 --- a/src/TorchSharp/Tensor/torch.BlasAndLapackOperations.cs +++ b/src/TorchSharp/Tensor/torch.BlasAndLapackOperations.cs @@ -131,7 +131,10 @@ public static Tensor addbmm_(Tensor input, Tensor batch1, Tensor batch2, float b // https://pytorch.org/docs/stable/generated/torch.cholesky + [Obsolete("torch.cholesky is deprecated in favor of torch.linalg.cholesky and will be removed in a future release. Use torch.linalg.cholesky instead.", false)] +#pragma warning disable CS0618 // Obsolete public static Tensor cholesky(Tensor input) => input.cholesky(); +#pragma warning restore CS0618 // https://pytorch.org/docs/stable/generated/torch.cholesky_inverse /// @@ -250,6 +253,7 @@ public static (Tensor A_LU, Tensor? pivots, Tensor? infos) lu(Tensor A, bool piv /// The pivots of the LU factorization from torch.lu() of size (∗,m), where *∗ is zero or more batch dimensions. /// The batch dimensions of LU_pivots must be equal to the batch dimensions of LU_data. /// + [Obsolete("torch.lu_solve is deprecated in favor of torch.linalg.lu_solve and will be removed in a future release. Use torch.linalg.lu_solve(LU, pivots, B) instead.", false)] public static Tensor lu_solve(Tensor b, Tensor LU_data, Tensor LU_pivots) { var solution = THSTensor_lu_solve(b.Handle, LU_data.Handle, LU_pivots.Handle); diff --git a/src/TorchSharp/Tensor/torch.cs b/src/TorchSharp/Tensor/torch.cs index 856df4dd2..83b59b604 100644 --- a/src/TorchSharp/Tensor/torch.cs +++ b/src/TorchSharp/Tensor/torch.cs @@ -16,7 +16,10 @@ public static partial class torch /// The input matrix /// If upper is true, the returned matrix U is upper-triangular. If upper is false, the returned matrix L is lower-triangular /// + [Obsolete("torch.cholesky is deprecated in favor of torch.linalg.cholesky and will be removed in a future release. Use torch.linalg.cholesky instead.", false)] +#pragma warning disable CS0618 // Obsolete public static Tensor cholesky(Tensor input, bool upper) => input.cholesky(upper); +#pragma warning restore CS0618 /// /// Returns the matrix norm or vector norm of a given tensor. diff --git a/test/TorchSharpTest/LinearAlgebra.cs b/test/TorchSharpTest/LinearAlgebra.cs index d2d4d02f9..29d96c4f8 100644 --- a/test/TorchSharpTest/LinearAlgebra.cs +++ b/test/TorchSharpTest/LinearAlgebra.cs @@ -49,7 +49,7 @@ public void TestLUSolve() Assert.Equal(new long[] { 2, 3, 3 }, A_LU.shape); Assert.Equal(new long[] { 2, 3 }, pivots.shape); - var x = lu_solve(b, A_LU, pivots); + var x = linalg.lu_solve(A_LU, pivots, b); Assert.Equal(new long[] { 2, 3, 1 }, x.shape); var y = norm(bmm(A, x) - b); @@ -67,7 +67,7 @@ public void TestLUSolve() Assert.Equal(new long[] { 2, 3 }, pivots.shape); Assert.Equal(new long[] { 2 }, infos.shape); - var x = lu_solve(b, A_LU, pivots); + var x = linalg.lu_solve(A_LU, pivots, b); Assert.Equal(new long[] { 2, 3, 1 }, x.shape); var y = norm(bmm(A, x) - b); From 5768b9f7f04f80239ab036eb6f63711cd3635104 Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Wed, 25 Feb 2026 11:58:32 +0100 Subject: [PATCH 2/3] Address PR review: improve cholesky comment and add upper=true test - Reword THSTensor_cholesky comment to clarify we use the default lower-triangular form and conjugate-transpose for upper=true - Add CholeskyUpperTest to validate upper=true path after migration from deprecated torch::cholesky to torch::linalg_cholesky Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Native/LibTorchSharp/THSLinearAlgebra.cpp | 3 ++- test/TorchSharpTest/LinearAlgebra.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Native/LibTorchSharp/THSLinearAlgebra.cpp b/src/Native/LibTorchSharp/THSLinearAlgebra.cpp index 8a3e747b6..c1c8a620f 100644 --- a/src/Native/LibTorchSharp/THSLinearAlgebra.cpp +++ b/src/Native/LibTorchSharp/THSLinearAlgebra.cpp @@ -359,7 +359,8 @@ Tensor THSLinalg_lu_solve(const Tensor B, const Tensor LU, const Tensor pivots, Tensor THSTensor_cholesky(const Tensor tensor, const bool upper) { // torch::cholesky is deprecated in favor of torch::linalg_cholesky. - // linalg_cholesky always returns lower-triangular; use .mH() for upper. + // Here we call torch::linalg_cholesky with its default (lower-triangular) output, + // and return its conjugate transpose via .mH() when upper is true. CATCH_TENSOR(upper ? torch::linalg_cholesky(*tensor).mH() : torch::linalg_cholesky(*tensor)) } diff --git a/test/TorchSharpTest/LinearAlgebra.cs b/test/TorchSharpTest/LinearAlgebra.cs index 29d96c4f8..e6940441d 100644 --- a/test/TorchSharpTest/LinearAlgebra.cs +++ b/test/TorchSharpTest/LinearAlgebra.cs @@ -305,6 +305,20 @@ public void CholeskyTest() Assert.True(a.allclose(l.matmul(l.swapaxes(-2, -1)))); // Worked this in to get it tested. Alias for 'transpose' } + [Fact] + [TestOf(nameof(Tensor.cholesky))] + public void CholeskyUpperTest() + { + var a = randn(new long[] { 3, 2, 2 }, float64); + a = a.matmul(a.swapdims(-2, -1)); +#pragma warning disable CS0618 // Obsolete + var u = a.cholesky(upper: true); +#pragma warning restore CS0618 + + // U should be upper-triangular: U^T * U == A + Assert.True(a.allclose(u.swapaxes(-2, -1).matmul(u))); + } + [Fact] [TestOf(nameof(linalg.cholesky_ex))] public void CholeskyExTest() From f7ad367ae235d1e9a9ef90bda630942f59293e19 Mon Sep 17 00:00:00 2001 From: Stefan-Alin Pahontu <56953855+alinpahontu2912@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:08:26 +0200 Subject: [PATCH 3/3] Update test/TorchSharpTest/LinearAlgebra.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- test/TorchSharpTest/LinearAlgebra.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TorchSharpTest/LinearAlgebra.cs b/test/TorchSharpTest/LinearAlgebra.cs index e6940441d..2d085d1d0 100644 --- a/test/TorchSharpTest/LinearAlgebra.cs +++ b/test/TorchSharpTest/LinearAlgebra.cs @@ -315,7 +315,7 @@ public void CholeskyUpperTest() var u = a.cholesky(upper: true); #pragma warning restore CS0618 - // U should be upper-triangular: U^T * U == A + // U should be upper-triangular: for real inputs U^T * U == A (more generally, U^H * U == A) Assert.True(a.allclose(u.swapaxes(-2, -1).matmul(u))); }