Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

ko_fi: cwoltering
liberapay: cwoltering
custom: ['http://wo80.bplaced.net/donate.html']
custom: ['https://wo80.webspace.rocks/donate/']
6 changes: 3 additions & 3 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v5
- name: Setup .NET
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v5
with:
dotnet-version: 8.0.x
dotnet-version: 10.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
Expand Down
125 changes: 125 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
### Version 4.3.0 - 2025-11-11

* Add net10.0 and remove net6.0 target framework.
* Minor optimizations for matrix-vector multiplication.
* Minor optimizations checking empty Span.

### Version 4.2.0 - 2024-09-15

* Make `SymbolicColumnStorage` class public and update `StronglyConnectedComponents` and `DulmageMendelsohn` decomposition accordingly.

### Version 4.1.0 - 2024-06-14

* Add overload for creating a sparse matrix from an enumerable of `ValueTuple`.
* Add matrix `EnumerateIndexedAsValueTuples()` to enumerate entries as `ValueTuple`.

### Version 4.0.0 - 2024-04-03

The major version change is due to the removal of obsolete methods in the `Converter` class. Visibility of that class was changed from public to internal. In case those obsolete methods were still used, please switch to the static conversion methods provided by the `SparseMatrix` class.

Additional changes:

* Add helper method `Helper.ValidateStorage(...)` to validate the structure of a sparse matrix.
* Update to `GetHashCode()` method of `CompressedColumnStorage` class.
* Improvements to documentation.

### Version 3.8.1 - 2023-11-15

* Add overloads for permutation `Invert()` and `IsValid()` methods taking the permutation length as argument.

### Version 3.8.0 - 2023-05-20

* Add overloads for the factorization `Solve()` methods taking `Span<T>` as argument. Note that this introduces a dependency on `System.Memory` for the netstandard2.0 assembly.

### Version 3.7.0 - 2022-05-04

* Add sparse matrix `OfDiagonals` static method (similar to MATLAB spdiags).

### Version 3.6.0 - 2021-11-25

* Remove .NET 4.5 target framework, upgrade .NET 5.0 to 6.0.
* Add constructor that takes explicit non-zeros count to `CoordinateStorage` class.

### Version 3.5.0 - 2021-01-14

* Remove .NET 4.0 target framework, add .NET 5.0.

### Version 3.4.9 - 2020-11-06

* Add `CoordinateStorage` constructor that uses existing storage arrays.
* Convert `CoordinateStorage` to sparse matrix in place.

### Version 3.4.7 - 2020-08-28

* BREAKING: make `SparseLDL` constructor private (use static create methods instead).
* Add complex version of `SparseLDL`.
* Add `matrix.EnumerateIndexed(action)` overload.

### Version 3.4.6 - 2020-07-21

* Add `SolveTranspose` method for `SparseQR`.

### Version 3.4.5 - 2020-06-11

This release introduces the static `SparseMatrix.AutoTrimStorage` option, which enables control over hidden memory allocations in matrix addition and multiplication. By default, the matrix storage will be resized to exactly fit the non-zeros count, which involves new memory allocations. If you want to avoid this, set `AutoTrimStorage` to `false`.

Additional changes:

* Add public helper methods `Helper.TrimStrorage(...)` and `Helper.SortIndices(...)`
* Add `DenseMatrix.OfJaggedArray(...)`

### Version 3.4.3 - 2020-05-25

* Add a sparse matrix multiplication overload that accepts the result matrix as a parameter.

### Version 3.4.2 - 2020-05-13

* Make CSparse.NET CLS compliant
* Mark public methods of Converter class as obsolete

### Version 3.4.1 - 2019-10-02

* Improved validation of matrix constructor arguments
* Fixes an issue with `CoordinateStorage` throwing `IndexOutOfRangeException` (introduced in v3.4.0)

### Version 3.4.0 - 2019-09-15

* Parallel dense and sparse matrix multiplication (by Andreas Girgensohn)
* General performance improvements for sparse matrix addition and multiplication

### Version 3.3.0 - 2019-04-29

* Support more target frameworks (including netstandard2.0).
* Public access to members of Dulmage-Mendelsohn decomposition.
* Compute strongly connected components.

### Version 3.2.3 - 2018-11-30

* Added matrix creation helper (e.g. call `SparseMatrix.OfIndexed(s)` to convert coordinate storage).

### Version 3.2.2 - 2018-10-12

* Added MatrixMarket writer.
* BREAKING: make `IProgress interface` compatible with .NET 4.5.

### Version 3.2.1 - 2018-09-17

### Version 3.2.0 - 2018-03-09

* Added new `DenseMatrix` type.
* BREAKING: removed deprecated `CompressedColumnStorage` type.
* BREAKING: removed deprecated `matrix.Norm(int)` method.

### Version 3.1.10 - 2018-03-06

* Rename `CompressedColumnStorage` to `SparseMatrix`.
* BREAKING: `matrix.Multiply(x, y)` overwrites y (instead of update).
* BREAKING: sparse matrix `PermuteColumns` returns a new matrix (instead of update).

### Version 3.1.9 - 2017-01-06

* BREAKING: use static `Create` methods (e.g. `SparseLU.Create(...)`) instead of constructors.

### Version 3.1.4 - 2015-09-19

* Initial release of CSparse.NET (based on Tim Davis CSparse version 3.1.4)
8 changes: 4 additions & 4 deletions CSparse.Tests/CSparse.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down Expand Up @@ -41,9 +41,9 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="NUnit" Version="4.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="5.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
9 changes: 9 additions & 0 deletions CSparse.Tests/Complex/Factorization/SparseLUTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace CSparse.Tests.Complex.Factorization
using CSparse.Complex;
using CSparse.Complex.Factorization;
using NUnit.Framework;
using System;
using Complex = System.Numerics.Complex;

public class SparseLUTest
Expand Down Expand Up @@ -30,6 +31,14 @@ public void TestSolve()
A.Multiply(-1.0, x, 1.0, r);

Assert.That(Vector.Norm(r.Length, r) < EPS, Is.True);

// Test exceptions:

var e1 = Assert.Throws<ArgumentNullException>(() => lu.Solve(b, null));
var e2 = Assert.Throws<ArgumentNullException>(() => lu.Solve(null, x));

Assert.That(e1.ParamName, Is.EqualTo("result"));
Assert.That(e2.ParamName, Is.EqualTo("input"));
}

[Test]
Expand Down
9 changes: 9 additions & 0 deletions CSparse.Tests/Double/Factorization/SparseLUTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace CSparse.Tests.Double.Factorization
using CSparse.Double;
using CSparse.Double.Factorization;
using NUnit.Framework;
using System;

public class SparseLUTest
{
Expand All @@ -29,6 +30,14 @@ public void TestSolve()
A.Multiply(-1.0, x, 1.0, r);

Assert.That(Vector.Norm(r.Length, r) < EPS, Is.True);

// Test exceptions:

var e1 = Assert.Throws<ArgumentNullException>(() => lu.Solve(b, null));
var e2 = Assert.Throws<ArgumentNullException>(() => lu.Solve(null, x));

Assert.That(e1.ParamName, Is.EqualTo("result"));
Assert.That(e2.ParamName, Is.EqualTo("input"));
}

[Test]
Expand Down
5 changes: 3 additions & 2 deletions CSparse.sln
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31025.194
# Visual Studio Version 17
VisualStudioVersion = 17.14.36705.20 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSparse", "CSparse\CSparse.csproj", "{BE369FD3-02F6-4A13-8DA2-E44A819FAE3C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSparse.Tests", "CSparse.Tests\CSparse.Tests.csproj", "{84D239FA-7BA0-4E5D-89FF-C29C5267CDB0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A01A8F54-DCC1-4E01-B6B4-1C653B382D30}"
ProjectSection(SolutionItems) = preProject
CHANGELOG.md = CHANGELOG.md
README.md = README.md
EndProjectSection
EndProject
Expand Down
43 changes: 24 additions & 19 deletions CSparse/CSparse.csproj
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net8.0;net10.0</TargetFrameworks>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<PackageId>CSparse</PackageId>
<Summary>A concise library for solving sparse linear systems with direct methods.</Summary>
<Description>CSparse.NET provides numerical methods for sparse LU, Cholesky and QR decomposition of real and complex linear systems.</Description>
<Product>CSparse.NET</Product>
<Company />
<Copyright>Copyright Christian Woltering © 2012-2024</Copyright>
<Copyright>Copyright Christian Woltering © 2012-2025</Copyright>
<Authors>Christian Woltering</Authors>
<AssemblyVersion>4.2.0.0</AssemblyVersion>
<FileVersion>4.2.0.0</FileVersion>
<AssemblyVersion>4.3.0.0</AssemblyVersion>
<FileVersion>4.3.0.0</FileVersion>
<PackageTags>math sparse matrix lu cholesky qr decomposition factorization </PackageTags>
<Version>4.2.0</Version>
<Version>4.3.0</Version>
<AssemblyName>CSparse</AssemblyName>
<RootNamespace>CSparse</RootNamespace>
<PackageLicenseExpression>LGPL-2.1-only</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/wo80/CSparse.NET</PackageProjectUrl>
<RepositoryUrl>https://github.com/wo80/CSparse.NET.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageReleaseNotes>
Version 4.2.0
<PackageReleaseNotes>Version 4.3.0

* Make SymbolicColumnStorage class public and update StronglyConnectedComponents and DulmageMendelsohn decomposition accordingly.
* Add net10.0 and remove net6.0 target framework.
* Minor optimizations for matrix-vector multiplication.
* Minor optimizations checking empty Span.

Version 4.1.0
Version 4.2.0

* Add overload for creating a sparse matrix from an enumerable of ValueTuple.
* Add matrix EnumerateIndexedAsValueTuples() to enumerate entries as ValueTuple.
* Make SymbolicColumnStorage class public and update StronglyConnectedComponents and DulmageMendelsohn decomposition accordingly.

Version 4.0.0
Version 4.1.0

The major version change is due to the removal of obsolete methods in the Converter class. Visibility of that class was changed from public to internal. In case those obsolete methods were still used, please switch to the static conversion methods provided by the SparseMatrix class.
* Add overload for creating a sparse matrix from an enumerable of ValueTuple.
* Add matrix EnumerateIndexedAsValueTuples() to enumerate entries as ValueTuple.

Other changes in this version:
Version 4.0.0

* Addition of helper method Helper.ValidateStorage(...) to validate the structure of a sparse matrix.
* Update to GetHashCode() method of CompressedColumnStorage class.
* Improvements to documentation.
</PackageReleaseNotes>
The major version change is due to the removal of obsolete methods in the Converter class. Visibility of that class was changed from public to internal. In case those obsolete methods were still used, please switch to the static conversion methods provided by the SparseMatrix class.

Other changes in this version:

* Addition of helper method Helper.ValidateStorage(...) to validate the structure of a sparse matrix.
* Update to GetHashCode() method of CompressedColumnStorage class.
* Improvements to documentation.
</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.5" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
<PackageReference Include="System.Memory" Version="4.6.3" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions CSparse/Complex/Factorization/SparseCholesky.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ public int NonZerosCount
/// <param name="result">The left hand side vector, <c>x</c>.</param>
public void Solve(ReadOnlySpan<Complex> input, Span<Complex> result)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (input.IsEmpty) throw new ArgumentNullException(nameof(input));

if (result == null) throw new ArgumentNullException(nameof(result));
if (result.IsEmpty) throw new ArgumentNullException(nameof(result));

var x = this.temp;

Expand Down
4 changes: 2 additions & 2 deletions CSparse/Complex/Factorization/SparseLDL.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ public int NonZerosCount
/// <param name="result">Solution vector x.</param>
public void Solve(ReadOnlySpan<Complex> input, Span<Complex> result)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (input.IsEmpty) throw new ArgumentNullException(nameof(input));

if (result == null) throw new ArgumentNullException(nameof(result));
if (result.IsEmpty) throw new ArgumentNullException(nameof(result));

var x = temp;

Expand Down
8 changes: 4 additions & 4 deletions CSparse/Complex/Factorization/SparseLU.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ public int NonZerosCount
/// <param name="result">The left hand side vector, <c>x</c>.</param>
public void Solve(ReadOnlySpan<Complex> input, Span<Complex> result)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (input.IsEmpty) throw new ArgumentNullException(nameof(input));

if (result == null) throw new ArgumentNullException(nameof(result));
if (result.IsEmpty) throw new ArgumentNullException(nameof(result));

var x = this.temp;

Expand All @@ -153,9 +153,9 @@ public void Solve(ReadOnlySpan<Complex> input, Span<Complex> result)
/// <param name="result">The left hand side vector, <c>x</c>.</param>
public void SolveTranspose(ReadOnlySpan<Complex> input, Span<Complex> result)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (input.IsEmpty) throw new ArgumentNullException(nameof(input));

if (result == null) throw new ArgumentNullException(nameof(result));
if (result.IsEmpty) throw new ArgumentNullException(nameof(result));

var x = this.temp;

Expand Down
8 changes: 4 additions & 4 deletions CSparse/Complex/Factorization/SparseQR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ private SparseQR(int rows, int columns)
/// </remarks>
public override void Solve(ReadOnlySpan<Complex> input, Span<Complex> result)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (input.IsEmpty) throw new ArgumentNullException(nameof(input));

if (result == null) throw new ArgumentNullException(nameof(result));
if (result.IsEmpty) throw new ArgumentNullException(nameof(result));

var x = new Complex[S.m2];

Expand Down Expand Up @@ -154,9 +154,9 @@ public override void Solve(ReadOnlySpan<Complex> input, Span<Complex> result)
/// <param name="result">The left hand side vector, <c>x</c>.</param>
public void SolveTranspose(ReadOnlySpan<Complex> input, Span<Complex> result)
{
if (input == null) throw new ArgumentNullException(nameof(input));
if (input.IsEmpty) throw new ArgumentNullException(nameof(input));

if (result == null) throw new ArgumentNullException(nameof(result));
if (result.IsEmpty) throw new ArgumentNullException(nameof(result));

int m2 = S.m2;

Expand Down
5 changes: 4 additions & 1 deletion CSparse/Complex/SparseMatrix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,18 @@ public override void Multiply(ReadOnlySpan<Complex> x, Span<Complex> y)
}

int end;
Complex xj;

for (int j = 0; j < columns; j++)
{
end = ap[j + 1];

xj = x[j];

// Loop over the rows
for (int k = ap[j]; k < end; k++)
{
y[ai[k]] += x[j] * ax[k];
y[ai[k]] += xj * ax[k];
}
}
}
Expand Down
Loading