CommunityToolkit / CommunityToolkit/dotnet

[(ReadOnly)Span2D] Expose `Stride`

Open
#453 0 comments 3 reactions 0 assignees View on GitHub
feature request :mailbox_with_mail:
Dominant language
C#
Stars
3.8k
Forks
400
PR merge metrics
No merged PRs in 30d

Description

### Overview

`Span2D` (and its read-only counterpart) seems perfect for numerical problems. When wanting to use numerical routines from HPC libraries the types do not expose the stride though. The stride is really helpful when calling a routine that accepts a pointer, number of rows, number of columns and a stride. Otherwise one would have to copy to contiguous memory first.

Some examples of routines that accept strides:
- in BLAS, e.g. here is dgemm [in Intel MKL](https://www.intel.com/content/www/us/en/develop/documentation/onemkl-developer-reference-fortran/top/blas-and-sparse-blas-routines/blas-routines/blas-level-3-routines/gemm.html) and [Reference LAPACK](https://netlib.org/lapack/explore-html/d1/d54/group__double__blas__level3_gaeda3cbd99c8fb834a60a6412878226e1.html) Arguments `ldx` refer to the leading dimension of `x` which is the stride (but here in column-major)
- here is another routine, this time row-major, [from the NAG Library](https://www.nag.com/numeric/nl/nagdoc_latest/clhtml/g02/g02brc.html#tdx), `tdx` is the stride argument

### API breakdown

https://github.com/CommunityToolkit/dotnet/blob/e6257d8c65126f2f977f2dcbce3fe6045086f270/CommunityToolkit.HighPerformance/Memory/Span2D%7BT%7D.cs#L89-L96

makes this part public, i.e.
```csharp
public readonly int Stride;
```

Same for `ReadOnlySpan`

### Usage example

```csharp
private static unsafe extern dgemv(char trans, int m, int n, double alpha, double* a,
int ldA, double* x, double incX, double beta, double* y, int incY);

public static unsafe dgemv(double alpha, ReadOnlySpan2D a, ReadOnlySpan x,
double beta, Span y)
{
// Dimension check skipped

fixed (double* aPtr = a, xPtr = x, yPtr = y)
{
dgemv('T', a.Height, a.Width, alpha, aPtr, a.Stride, xPtr, 1, beta, yPtr, 1);
}
}
```

### Breaking change?

No

### Alternatives

Use `TryGetSpan` and if it doesn’t work copy discontiguous 2D spans to contiguous 1D spans first.

### Additional context

This seems like a small PR I could create if the change in visibility doesn’t have any unintended consequences (I don’t see any). But it’d be good if someone could assess that first.

### Help us help you

Yes, I'd like to be assigned to work on this item

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.