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#
- Host: GitHub
- URL: https://github.com/losttech/typenum
- Owner: losttech
- License: apache-2.0
- Created: 2019-03-21T02:25:17.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2024-01-12T00:33:26.000Z (about 2 years ago)
- Last Synced: 2025-04-20T01:33:02.419Z (10 months ago)
- Language: C#
- Size: 48.8 KB
- Stars: 11
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# TypeNum
Type-level integers for C#
[](https://www.nuget.org/packages/TypeNum/)
[](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
```