Nerd_STF 3.1.0

dotnet add package Nerd_STF --version 3.1.0
                    
NuGet\Install-Package Nerd_STF -Version 3.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nerd_STF" Version="3.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nerd_STF" Version="3.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Nerd_STF" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nerd_STF --version 3.1.0
                    
#r "nuget: Nerd_STF, 3.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nerd_STF@3.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nerd_STF&version=3.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Nerd_STF&version=3.1.0
                    
Install as a Cake Tool

Nerd_STF

Nerd_STF is a multi-purpose library for .NET focused primarily on mathematics. It supports basically all versions of .NET has plenty of flexibility to let you do what you please with it.

Contents

Examples

Here's how to derive a polynomial in Nerd_STF:

using Nerd_STF.Mathematics.Equations;

Polynomial poly = new(2, 1, 3); // 2x^2 + x + 3
Polynomial derivative = poly.Derive();

Console.WriteLine(derivative);  // Output: 4x + 1

Here's how to get or set part of a number group:

Float3 xyz = (1, 2, 3);

Float2 xy = new(xyz["xy"]);
Float2 zy = new(xyz["zy"]);
double[] yxzy = [.. xyz["yxzy"]];

xyz["yz"] = [7, 8];
Console.WriteLine(xyz); // Output: (1, 7, 8)

Pretty easy, right?

How to Install

NuGet

You can install the package very easily with the NuGet Package Manager. The link to its NuGet page is here. You could install it by running a command:

# Do not include version flag to download the latest release.
dotnet add package Nerd_STF --version 3.0

or by including a package reference element in your project file:


<PackageReference Include="Nerd_STF" Version="3.0" />

Manual Reference

You could also manually reference the DLL for the project. Go to the releases page and select the library version and .NET target of your choice. At the time of writing, this project compiles to .NET Standard 1.3, 2.1, and .NET 7.0, but more may be added in the future.

Place the DLL somewhere you'll be able to reference later.

If you're using Visual Studio 2019 or 2022:

  • Right click the project icon in the hierarchy.
  • Go to Add > Project Reference
  • Click Browse and locate the DLL you saved earlier.
  • Click OK. You should be good to go!

Otherwise, you'll have to add a project reference element in your project file somewhere.

<Reference Include="Nerd_STF">
  <HintPath>path\to\your\download\Nerd_STF.3.0.NET7.0.dll</HintPath>
</Reference>

I found a bug!

I'm not surprised, I'm only one guy. Feel free to make an issue in the repository and I'll get to it when I can!

I'd like to contribute!

Well, I'd prefer to do most of the programming myself, but if anyone wants to submit a pull request, feel free! Stick to the version-specific branches, try not to make commits on the main branch.

When's your next release?

No idea. This is a pet project, so progress on this library will come and go. It was more than a year between versions 2.4.1 and 3.0. It's really whenever mood strikes, so just watch the project to see what the current status is.

Older Versions

3.0 has plenty of breaking changes from 2.4.1 (and the rest of the 2.x updates), so it's totally fine if you don't want to update. I'll keep the 2.x updates up for the long-term, no reason to remove them. As for the versions before 2.0, well, it wasn't even really a library at that point. Do with it what you will.

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp1.0 was computed.  netcoreapp1.1 was computed.  netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 is compatible.  netcoreapp3.1 was computed. 
.NET Standard netstandard1.1 is compatible.  netstandard1.2 was computed.  netstandard1.3 is compatible.  netstandard1.4 was computed.  netstandard1.5 was computed.  netstandard1.6 was computed.  netstandard2.0 was computed.  netstandard2.1 is compatible. 
.NET Framework net45 was computed.  net451 was computed.  net452 was computed.  net46 is compatible.  net461 was computed.  net462 is compatible.  net463 was computed.  net47 is compatible.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen30 was computed.  tizen40 was computed.  tizen60 was computed. 
Universal Windows Platform uap was computed.  uap10.0 was computed. 
Windows Phone wpa81 was computed. 
Windows Store netcore was computed.  netcore45 was computed.  netcore451 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.1.0 33 1/2/2026
3.0.0 342 9/18/2025
3.0.0-beta3 162 2/19/2025
3.0.0-beta2 162 11/25/2024
3.0.0-beta1 140 10/29/2024
2.4.1 381 7/17/2023
2.4.0 291 7/10/2023
2.3.2 390 3/9/2023
2.3.1.68 496 11/12/2022
2.3.1.52-alpha 498 10/31/2022 2.3.1.52-alpha is deprecated because it has critical bugs.
2.3.1.39-alpha 489 9/30/2022 2.3.1.39-alpha is deprecated because it has critical bugs.
2.3.0 571 8/2/2022
2.2.0 601 6/10/2022
2.1.2 616 5/2/2022
2.1.1 559 4/17/2022
2.1.0 610 4/17/2022
2.0.1 595 4/3/2022
2.0.0 603 4/3/2022

# Nerd_STF v3.1

Hi! It's been a while, but I've got a few things for you guys.

## More color configurations.

I've been spending a lot of my time recently working on [a Java library for FRC light strips](https://github.com/That-One-Nerd/betterlights) and in the process I made a tool for gradients. I ended up finding myself wishing I had it in here, too, so I've added it.

It functions mostly as a list of colors and associated positions for those colors. You can add and remove colors over time, and you index it (or call `.Get()`) with a value between 0 and 1 to determine a color. For example:

```csharp
Gradient<ColorRGB> gradient = new()
{
   { 0.0, ColorRGB.Red },
   { 0.5, ColorRGB.Green },
   { 1.0, ColorRGB.Blue },
};

Console.WriteLine(gradient[0.2].HexCode()); // #996600
```

You can also quickly and easily visualize your gradients right in the console, so long as your console has compatibility for RGB colors.

```
Console.WriteLine("Our gradient: " + gradient.ToColorString());
```
produces this in the terminal:
<img width="590" height="38" alt="image" src="https://github.com/user-attachments/assets/692b9263-a4f6-4a18-97af-71e9ce830f34" />
<sub>Note that the resulting preview is actually a 1668 character string behind the scenes.</sub>

You can change the way the colors interpolate, if you'd like. Simply set `gradient.Interpolation` to any function that takes two colors and a float, and outputs a color.

```csharp
Gradient<ColorRGB> gradient = new()
{
   { 0.0, ColorRGB.Red },
   { 0.5, ColorRGB.Green },
   { 1.0, ColorRGB.Blue },
};

// Interpolate through white. Don't look at the implementation too
// much, the point is to demonstrate that it can be set to whatever.
gradient.Interpolation = (a, b, t) =>
{
   ColorRGB c;
   if (t <= 0.5) (c, t) = (a, t * 2);
   else (c, t) = (b, -2 * t + 2);
   return (t, t, t) + c * (1 - t);
};
Console.WriteLine("        Through White: " + gradient.ToColorString() + "\n");

// Or you can set it to some simple templates.
gradient.Interpolation = Gradient<ColorRGB>.Nearest;
Console.WriteLine("     Nearest Neighbor: " + gradient.ToColorString() + "\n");

gradient.Interpolation = Gradient<ColorRGB>.Lerp;
Console.WriteLine("Default Interpolation: " + gradient.ToColorString() + "\n");
```

For the result:
<img width="666" height="105" alt="image" src="https://github.com/user-attachments/assets/96c17685-5817-4d70-bdb9-241cb6735309" />

### `ColorYCC`

In addition, I have also implemented the YC<sub>b</sub>C<sub>r</sub> color space in the `ColorYCC` class. [YCbCr](https://en.wikipedia.org/wiki/YCbCr) is a way to convert RGB colors into a luminance value and two chrominance values. The conversion relies on the constants K<sub>r</sub>, K<sub>g</sub>, and K<sub>b</sub>, which can be statically modified in the class. The constants are set to what I'm fairly certain is the most common standard, but the conversion system works for any $K_r + K_g + K_b = 1$.

## `Validatable<T>`

A small object I created mostly for the purposes of RGB <-> YCC conversion. It's done using matrix and vector multiplication, so I've cached the matrices required. However, if the K constants ever got changed, the matrix and its inverse needed to be recomputed. This is the purpose of the `Validatable` class.

When constructed, a method must be passed that "generates" a valid value when requested.
`Validatable<int> obj = new(() -> ...);`

Afterwards, when `obj.Value` is read, the object either runs the generation function and caches the result, or returns an already cached result.

To force the object to re-generate a value, simply declare it invalidated by `obj.Invalidate()`. This will cause the generator to be re-invoked *only when required*. It's essentially a re-usable version of `System.Lazy<T>`.

## Discrete Math

I took discrete math last semester and decided to implement some of the things we discussed in that class here. Namely, the `Nerd_STF.Mathematics.Discrete` namespace contains mathematically-defined sets and relations. I think I went a little overboard with the abstraction here, I may use a better system in the future. But the important types to note are the `DiscreteSet<T>` and `DiscreteRelation<T1, T2>` types. The `DiscreteSet` contains a unique set of elements of type `T`, and a relation is a mapping of one set to another. Here's an example.

```csharp
DiscreteSet<int> evens = [], odds = [], primes = [];
for (int i = 0; i < 20; i++)
{
   if (i % 2 == 0) evens += i;
   else odds += i;

   if (IsPrime(i)) primes += i;
}
Console.WriteLine($"Evens set: {evens}\nOdds set: {odds}\nPrimes set: {primes}");

DiscreteRelation<int, int> relation = new();
foreach (int odd in odds)
{
   if (odd == 1) continue;
   foreach (int even in evens)
   {
       if (even % (odd - 1) == 0) relation += (even, odd);
   }
}
Console.WriteLine("\nRelation between evens and odds:\n" + relation);
```

Yields:
<img width="1083" height="158" alt="image" src="https://github.com/user-attachments/assets/028d1c09-6074-420f-9c34-71c93eaf9348" />

Some things were handled better than others. The source code of the `DiscreteRelation` class specifically is a scuffed mess of long type names and abstraction, and none of this is particularly fast or efficient, but it works for simple situations and isn't too abstraction-heavy on the part of the user of this library.

## Some final thoughts.

I may in the future condense `DiscreteRelation<T1, T2>` into a single type parameter for both the input and output. It makes things like the relation matrix and symmetry detection easier to implement.

I don't think I'm done with graphics. I've got some more ideas in the pipeline, but this library obviously takes a while to work on.

I also have a ton of very small tweaks I want to make. Things such as clamping color values in the constructors, or getting rid of `SplitArray` because the `System.Linq` namespace basically does that in a more modular way. Some small patches may be in order, but releasing this is such a pain I like to do it in bulk.

---

Take care, and enjoy 3.1!