Choosing the Right Vector/Matrix Type

The API has 73 types matching "Vec/Mtx/Vector/Matrix", but only 18 are data containers. The rest are base classes, exceptions, converters, and infrastructure.

Two-question decision tree:

Q1: What element type do you need?

Element type1D (vector)2D (matrix)Notes
Double (default)Vector / TVecMatrix / TMtx90%+ of use cases
IntegerVectorInt / TVecIntMatrixInt / TMtxInt
GPU (OpenCL)clVectorclMatrixGPU compute only
SparseTSparseMtxSparse storage only
Byte / SmallIntTVecByte / TMtxByteTVecSmallInt / TMtxSmallIntRare, compact

Q2: Value type or pool-managed?

ChoiceTypesWhen to use
Value type (default)Vector, Matrix, VectorInt, MatrixIntGeneral use, operator overloading, automatic lifetime
Pool-managedTVec, TMtx, TVecInt, TMtxIntBlock processing loops with CreateIt/FreeIt for L1 cache discipline

See topic declaration-rules for where each type may be declared (local var vs field) and the correct construction patterns.

Relationship between value types and pool-managed types:

Vector wraps a TVec internally, Matrix wraps a TMtx, and so on. They share the same underlying data object. This has two important consequences:

  1. Automatic conversion when passing to methods: When you pass a Vector to a method that accepts TVec (or TMtxVec), the value type automatically converts and dereferences its internal object. No cast needed — just pass it directly. This is also why methods are declared with TVec/TMtx/TVecInt/TMtxInt parameters rather than Vector/Matrix: it allows them to accept both value types and pool-managed types, and when a value type is passed, one layer of encapsulation is stripped away making the code run faster.
  1. Typecast as an escape hatch: Every method that exists on TVec/TMtxVec is mirrored on Vector via thin delegates, so you almost never need to cast. If you do need the underlying TVec object directly — for example to pass it to a method that takes TVec explicitly — In C++ a Vector converts implicitly to TVec* (TVec* t = a;), and a-> calls the TVec members directly; neither copies the data.
Value typeWrapsAuto-converts to
VectorTVecTVec, TDenseMtxVec, TMtxVec
MatrixTMtxTMtx, TDenseMtxVec, TMtxVec
VectorIntTVecIntTVecInt, TMtxVecInt
MatrixIntTMtxIntTMtxInt, TMtxVecInt
  1. Accessing raw arrays:

In C++, PValues1D(0) returns a double* to the internal storage (zero-copy); PSValues1D, PCValues1D and PSCValues1D return float*, TCplx* and TSCplx* for the other storage precisions.

// C++: PValues1D returns a pointer to the internal storage
Vector b;
b.Size(10);
double* arr = b.PValues1D(0);      // direct pointer to internal storage
ProcessData(arr, b.GetLength());   // pass to functions that take double*
// Do not resize the Vector while arr is in use
  1. Do not dereference matrices to row arrays: TMtx stores data as a flat 1D block. Extracting a "row" from the Values 2D property does not produce a real independent array — In C++ there is no row array to take: Values(r, c) returns a reference to a single element, and SetSubRange gives the zero-copy view of a row.
// C++: a matrix has no row arrays to alias.
// Use SetSubRange for zero-copy row access:
Matrix m;
m.Size(10, 10);
Vector rowView;
rowView.SetSubRange(m, 0, 10);  // view of row 0

Rule: Never dereference TMtx/TMtxInt/Matrix/MatrixInt to row arrays. Use SetSubRange for zero-copy row access, or access elements through properties.

Memory layout — vectors and matrices share the same storage model:

Both vectors and matrices store their elements in a single contiguous block of memory. This means all element-wise methods that work on vectors (Sin, Add, Mul, etc.) can also be applied to matrices — they simply operate on the flat data block regardless of dimensionality. A matrix with 10 rows and 20 columns is stored as 200 contiguous doubles, identical in memory to a vector of length 200.

However, dimension-specific operations (row/column access, transposition, matrix multiplication, decompositions) require the matrix shape metadata and must use the dedicated matrix methods. The element-wise vector methods ignore row/column structure.

To obtain a zero-copy view of a portion of a matrix (or vector), use SetSubRange.

In C++ terms the view is a pointer and a length into the source storage: it shifts internal pointers without copying data.

// C++: Create a vector view of matrix row data (zero-copy)
Matrix m;
m.Size(10, 20);
Vector rowView;
rowView.SetSubRange(m, rowIndex * 20, 20);  // view of one row, no copy
rowView.Sin();          // operates on the matrix memory directly
rowView.SetSubRange();  // release view (restore to full range)

Key SetSubRange overloads:

  • a.SetSubRange(Src, Index, Len) — view of Src elements [Index..Index+Len-1]
  • a.SetSubRange(Src, Index, Rows, Cols) — view with matrix dimensions (on TMtx)
  • a.SetSubRange(Index, Len) — narrow the view of self (no source)
  • a.SetSubRange() — reset to full range (same as SetFullRange)

Important: The source must not be resized while a view exists. Call SetSubRange() (no args) to release the view when done.

Key insight about base classes in signatures:

  • Methods accept TVec/TMtx (not Vector/Matrix) by design — this accepts both types.
  • TMtxVec in a method signature means "pass any vector or matrix" (Vector, Matrix, TVec, TMtx, etc.) This is why element-wise operations accept both — the memory layout is the same.
  • TDenseMtxVec is the same — it's a polymorphic base, not a type you instantiate.
  • TMtxVecInt means pass VectorInt, MatrixInt, TVecInt, or TMtxInt.

Default choice: Use Vector (1D) or Matrix (2D). Switch to TVec/TMtx only in performance-critical block loops with explicit CreateIt/FreeIt lifecycle.