Creating Tensors

Tensors are created using methods of the static Tensor class.

Creating new tensors

The simplest way to create a new tensor is by calling the Create method with the desired dimensions of the tensor as arguments:

C#
var t1 = Tensor.Create<double>(3, 4);

The dimensions can also be supplied as a single TensorShape. In this case, an optional second argument specifies the order of elements in memory. By default, elements are laid out in 'C-style' (rows first or row-major) order, similar to .NET multidimensional arrays.

C#
var t2 = Tensor.Create<double>((3, 4), TensorElementOrder.CStyle);

Creating tensors from arrays and memory blocks

The elements of a tensor are often supplied in the form of an array. The CreateFromArray method allows for the easy creation of tensors from arrays. In its simplest form, the method simply takes an array as its only argument and returns a tensor with the same shape as the array and a copy of its elements:

C#
double[,] elements2D = { { 11, 12, 21 }, { 22, 31, 32 } };
var t3 = Tensor.CreateFromArray(elements2D);

When the array is one-dimensional or the element type is unmanaged, there is an optional second boolean argument that specifies whether the tensor should share its storage with the .NET array. This means that changes in the tensor are reflected in the array and vice versa.

Sometimes the elements of a multi-dimensional tensor are stored in a one-dimensional array. Two overloads of the CreateFromArray method are useful in this situation. The first two arguments are always the storage array and the desired shape of the tensor. The third argument specifies how the elements of the tensor are laid out in the storage array. This can be in the form of a TensorElementOrder value (either C-style, last dimension changes fasted or Fortran-style, first dimension changes fastest), or as a TensorLayout structure. An optional fourth argument specifies whether the tensor should be a view or whether the elements should be copied. The default is to create a copy. The example below creates the same 3x2 tensor using each of these options:

C#
double[] elements = { 11, 21, 31, 12, 22, 32 };
var t4 = Tensor.CreateFromArray(elements, (3, 2), TensorElementOrder.FortranStyle);
var layout = TensorLayout.FromStrides([ 3, 1 ]);
var t5 = Tensor.CreateFromArray(elements, (3, 2), layout);

When the elements are stored in a Memory<T> block, the CreateFromMemory method offers the same two overloads to create a tensor as CreateFromArray.

Other creation methods

Several other methods provide additional means of constructing tensors.

Creating ranges

The CreateRange method constructs a 1D tensor with linearly spaced elements. It takes up to 3 arguments. When one argument is provided, it returns a tensor with integers from 0 up to the argument value. When two arguments are provided, it returns a tensor with values from the first argument value up to the second argument value with unit increments. When three arguments are provided, it returns a vector with values from the first argument value up to the second argument value where the third argument specifies the total number of steps.

C#
var t7 = Tensor.CreateRange(10);
// t7 -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
var t8 = Tensor.CreateRange(5.0, 10.0);
// t8 -> [ 5.0, 6.0, 7.0, 8.0, 9.0 ]
var t9 = Tensor.CreateRange(5.0, 10.0, 5);
// t9 -> [ 5.0, 6.25, 7.5, 8.75, 10.0 ]

The CreateGeometricRange<T> method constructs a 1D tensor with geometrically spaced elements. The next element is equal to a constant factor times the previous element.

The CreateLogarithmicRange method is similar to CreateGeometricRange<T> but comes at it from a different angle. The logarithms of the elements are linearly spaced, which means that the elements are some base raised to a set of linearly spaced exponents. The range is specified by these logarithms or exponents. The default base is 10.

The example below creates the same range in two ways, first as a geometric range and then as a logarithmic range:

C#
var t7 = Tensor.CreateRange(10);
// t7 -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
var t8 = Tensor.CreateRange(5.0, 10.0);
// t8 -> [ 5.0, 6.0, 7.0, 8.0, 9.0 ]
var t9 = Tensor.CreateRange(5.0, 10.0, 5);
// t9 -> [ 5.0, 6.25, 7.5, 8.75, 10.0 ]

Random tensors

The CreateRandom method constructs a tensor with random elements. The first argument is the shape of the tensor. The second argument is the random number generator to use. This argument is optional.

The CreateRandomNormal method constructs a tensor with random elements from a standard normal distribution with mean zero and unit standard deviation. The first argument is once again the shape of the tensor. The second, optional argument is the random number generator to use.

C#
var v10 = Vector.CreateRandom(10, ArrayMutability.Immutable);
// v10 -> [ <10 random values between 0 and 1> ]
var v11 = Vector.CreateRandom(10, new MersenneTwister(17));
// v11 -> [ ]

Initializing tensors with a delegate

The CreateFromFunction method constructs a tensor of a specified shape and initializes the elements using a delegate. The first argument is the shape of the tensor. The second argument is a delegate that takes a set of indexes as parameters and returns the value of the tensor at these indexes. The delegate has as many parameters as there are dimensions in the tensor.

The next example constructs a tensor equivalent of a Hilbert matrix of order 10:

C#
var t14 = Tensor.CreateFromFunction((10, 10), (i, j) => 1.0 / (1.0 + i + j));