# What's New in Version 9.0

We’re thrilled to announce the release of version 9 of Numerics.NET.

## A new name

*Extreme Optimization* is now *Numerics.NET*, affirming our position
as the leading numerical library for .NET.

Version 9 completes our migration: Both the NuGet packages and the namespaces have been changed to reflect this.

This will require some changes in your projects, but migration should be pretty straightforward:

- Update the package references to
`Numerics.NET`

(see below). - Rename all
`Extreme.Mathematics`

namespace references to`Numerics.NET`

- Rename all remaining
`Extreme`

namespace references to`Numerics.NET`

If you encounter any challenges, we’re always here to help.

## NuGet packages

The packages are available on the NuGet Gallery.

All NuGet packages now start with the `Numerics.NET`

prefix. We’ve also reorganized
them in a more convenient way. The functionality is spread over several core packages,
while a number of bundles offer a simple way to get everything you need.

The main bundle packages are:

`Numerics.NET`

: bundles all managed packages. No native libraries are included.`Numerics.NET.win-x64`

: everything in`Numerics.NET`

plus processor-optimized native libraries for Windows (x64).`Numerics.NET.linux-x64`

: everything in`Numerics.NET`

plus processor-optimized native libraries for Linux (x64).

Of course you stil have the option of installing the individual packages if that is what you prefer.

## Linear algebra

### Tensors

A tensor is a generalization of vectors and matrices to arbitrary dimensions. With the growing popularity in areas such as machine learning and AI, the time has come to add support for tensors to Numerics.NET.

There is so much new here that we’ve written an entire post just on the topic of tensors in Numerics.NET: In Depth: Tensors.

Some of the features in Numerics.NET’s tensor type are not available in other tensor libraries include:

- Setting the destination of an operation, like
`Tensor.Add(left, right, result)`

. This avoids unnecessary allocations and can dramatically improve performance. - Memory layouts other than contiguous C-style (last index varies fastest). Much of the power and expressiveness of tensor libraries derives from the ability to rearrange the logical layout of the data while leaving the memory layout unchanged.
- Scalar tensors. A scalar tensor is a tensor with zero dimensions. This is useful in many algorithms, especially when working with tensors of different ranks.
- Aggregation along a specific dimension.
- Conditional evaluation. This is useful when you want to apply an operation only to certain elements of a tensor.
- Support for GPU and other platforms. Our tensor type is designed to be extensible so that, when provided with a suitable implementation, the same code can work on any platform, including GPU.

### Memory<T> based vector and matrix storage

In previous versions, vectors and matrices always used managed arrays to store their. This incurred a penalty when working with some native code because it was necessary to copy the data between managed and unmanaged memory.

In version 9, vectors and matrices now support using
`Memory<T>`

to store the elements.
This means you can create vectors and matrices directly
from native memory. No more copying needed!

### Spanified core API

The core implementations of linear algebra methods have been refitted
to use `Span<T>`

instead of arrays. This was a major undertaking
that enables better performance and more flexibility in the future.
For example, it is what allows us to use `Memory<T>`

for element storage.

The one drawback is that the new API is not compatible with C++/CLI,
which doesn’t support ref structs like `Span<T>`

. So, there are
no more mixed-mode native assemblies.

### Schur and QZ decompositions

Two new matrix decompositions make their debut in version 9.
The Schur decomposition writes a square matrix *A* as

where *Z* is orthogonal (unitary) and *T*, the *Schur form*
of *A*, is upper triangular.
The diagonal elements of *T* are also the eigenvalues of *A*.
For real matrices with complex eigenvalues, the real Schur form
of *A* is returned. This is an upper quasi-triangular matrix
where 2x2 blocks on the diagonal correspond to pairs of
complex conjugate eigenvalues.

Similar to eigensystems, there is also a generalization
of the Schur decomposition to two matrices. This
*generalized Schur decomposition*, also called
the *QZ decomposition*,
rewrites two square matrices *A* and *B* as

where again *S* and *T* are upper triangular,
and *Q* and *Z* are orthogonal (unitary).

## Mathematics

### Generic arithmetic

Numerics.NET has had facilities for the generic implementation of numerical algorithms for over a decade. Our linear algebra library has supported arbitrary numerical types since 2008!

We continue to build on this foundation. The new tensor library is of course generic over the element type, but there’s more.

Our generic arithmetic implementation is built on a static class, Operations<T>, that provides all common operations on numbers. Thanks to JIT optimizations, performance is on par with hard-coded types.

The Operations<T> class now fully supports complex numbers and nullable numeric types. We’ve also brought this class up to speed with all the latest updates to the System.Math class and numeric types in recent .NET versions.

All our special number types (Quad, BigInteger, BigRational, BigFloat)
implement the `INumber<T>`

interface introduced in .NET 7.0.
We’re not really happy with Microsoft’s work here.
While the introduction of these interfaces is clearly
a step forward in some ways, the way this was designed
has some serious problems.

For .NET 7.0+ only, we’ve added generic implementations of
some of the most common algorithms. The class names are
the same but there is an extra type argument, which must
implement `INumber<T>`

. To find the classes,
add `.Generic`

to the namespace of the original (non-generic)
class.

The following algorithms have a generic implementation:

- Numerical integration.
- Polynomial curve fitting, including using Chebyshev polynomials.
- Solving equations in one variable.

### Random number generators

We’ve added a new random number generator, PCG32, that is fast and compact. It is the new default random number generator.

Some new methods were recently added to .NET’s built-in random number generator. This includes GetItems, NextInt64 and NextSingle.

We’ve added implementations of these methods to our extended random number generator class so they are available to earlier .NET versions as well.

We’ve even added a few more! The `GetItems`

method
(introduced in .NET 8.0) returns a set of items
chosen at random from a set of choices *with replacement*.
This means that the same value can appear multiple times
in the output. Many applications require items that are chosen *without
replacement*. This means that every choice can appear
at most once in the output.
The GetItemsWithoutReplacement method does just that.

### Special functions

So-called *special functions* are a nearly limitless
group of funcions that appear in science. Some are
better known and more widely used than others.

In version 9, we’ve expanded our support for special functions considerably. We’ve added:

- Airy functions for complex argument.
- Bessel functions for complex argument.
- Kelvin functions.
- Monic Hermite polynomials.
- Jacobi polynomials.
- Bernoulli numbers and Bernoulli polynomials.
- Hurwitz zeta function and generalized harmonic numbers.
- Jacobi Epsilon and Zeta functions.

### Other improvements

- New optimized methods for computing norms of band matrices.
- An improved Quadratic Programming solver based on the algorithm of Goldfarb and Idnani.
- Performance improvements, including in 2D integration,
`BigFloat`

functions. - Take advantage of enhancements and new functionality in .NET whenever possible.

## Data Analysis

### Aggregators

The API around aggregators (like `Sum`

, `Variance`

) has been
overhauled to be more consistent and much more powerful.

Previously, there were two types of aggregators: normal
aggregators always returned a value of a specific type.
For example, computing the mean of an array always
returned a `double`

.

Aggregators now have an As<T> method that lets you change that. The input elements are converted to the result type. The converted elements are then used to compute the aggregate.

This is a breaking change. If you have code that depends on the type
of the result of an aggregator being fixed, you will need to update it.
For example, instead of `Aggregators.Mean`

, you now use `Aggregators.Mean.As<double>()`

.

All aggregators support skipping missing values in the input. More generally, you can apply any condition to the input values and only those values that meet the condition will be included in the aggregation.

### Accumulators

Internally, many of the aggregators use *accumulators*.
These are simple structures that incrementally accumulate
the result of the aggregation.

These accumulators have now been made public in the Numerics.NET.DataAnalysis.Accumulators namespace.

One accumulator can be the basis for several different aggregators. For example, the VarianceAccumulator<T> can return the count, the mean, as well as both the population and sample variance and standard deviation.

## Statistics

### New probability distributions

We’ve added a number of probability distributions. The following contiunous distributions are new in version 9:

- Arcsine distribution
- Hyperbolic distribution
- Inverse chi square distribution
- Inverse gamma distribution
- Inverse Gaussian distribution
- Inverse Weibull distribution
- Johnson family of distributions
- Maxwell distribution
- Normal inverse Gaussian distribution

Also new is the log-series distribution, a discrete distribution with applications in biology and finance.

### Improvements in statistical models

No major new features here.

- When performing stepwise regression, you can now get detailed information about each step.
- New diagnostics for linear regression:
Predicted residual error sum of squares (PRESS)
and Predicted R
^{2}.