An open API service indexing awesome lists of open source software.

https://github.com/losttech/typenum

Type-level integers for C#
https://github.com/losttech/typenum

Last synced: 9 months ago
JSON representation

Type-level integers for C#

Awesome Lists containing this project

README

          

# TypeNum
Type-level integers for C#

[![NuGet](https://img.shields.io/nuget/v/TypeNum.svg)](https://www.nuget.org/packages/TypeNum/)
[![Build Status](https://losttech.visualstudio.com/TypeNum/_apis/build/status/losttech.TypeNum?branchName=master)](https://losttech.visualstudio.com/TypeNum/_build/latest?definitionId=29&branchName=master)

# Example
```csharp
class Tensor
where NCols : struct, INumeral
where NRows : struct, INumeral
{
public static int ColumnCount { get; } = NCols.Num;
public static int RowCount { get; } = NRows.Num;

internal readonly float[,] values = new float[ColumnCount, RowCount];

public void Add(Tensor tensor)
{
for (int col = 0; col < ColumnCount; col++)
for (int row = 0; row < RowCount; row++)
this.values[col, row] += tensor.values[col, row];
}
}
```

## Shorthands
For non-power-of-two numerals it is useful to add shorthands.
Unfortunately declaring one is rather verbose in C#:
```csharp
using N39 = TypeNum.Sum,
TypeNum.N2>,
TypeNum.N1>;

...

Debug.Assert(N39.Num == 39);
var thirtyNine = new Tensor();
```

# Consistency
Technically, `Sum` and `Sum` represent the same numeral.
However, there is no way to express it in C# type system. To alleviate that
TypeNum tries to enforce one and only way to represent specific number.

To take advantage of that enforcement, avoid declaring your own implementations
of the `Numeral` interface, and stick to `N*`, `Twice`, and `Sum`
classes. They enforce several rules at run time (and, potentially, [compile
time in the future](https://github.com/losttech/TypeNum/issues/1)):

## Twice
In `Twice` `T` can only be one of the following:

* the largest predefined type numeral (currently `N4096`)
* another `Twice<*>`

So `Twice` can only be used to represent very large numerals

## Sum
The following rules are enforced on parameters `T1` and `T2` of `Sum`:

* `T1.Num` must be strictly greater (>) than `T2.Num` (swap them, if yours are opposite)
* `T2` can never be another `Sum<*,*>`. Replace any `Sum>` with
`Sum, C>`
* if `T1` itself is a `Sum
`, then in `Sum, C>` `A` and `B` must
each be strictly greater (>) than `C`

Following these rules will ensure, that equal type numerals are always
represented by identical types.

# F# Example
In F# (unlike C#) operators can introduce new generic type parameters,
which enables defining statically-typed matrix multiplication as an operator:

```fsharp
type Matrix<'rows, 'cols>() =
static member ( * )(left: Matrix<'rows, 'cols>, right: Matrix<'cols, 'ncols>) =
Matrix<'rows, 'ncols>()

module private Test =
open TypeNum

type N3 = Sum
type N7 = Sum
type N5 = Sum

let a = Matrix()
let b = Matrix()
let product = a * b

```