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 type | 1D (vector) | 2D (matrix) | Notes |
|---|---|---|---|
| Double (default) | Vector / TVec | Matrix / TMtx | 90%+ of use cases |
| Integer | VectorInt / TVecInt | MatrixInt / TMtxInt | |
| GPU (OpenCL) | clVector | clMatrix | GPU compute only |
| Sparse | — | TSparseMtx | Sparse storage only |
| Byte / SmallInt | TVecByte / TMtxByte | TVecSmallInt / TMtxSmallInt | Rare, compact |
Q2: Value type or pool-managed?
| Choice | Types | When to use |
|---|---|---|
| Value type (default) | Vector, Matrix, VectorInt, MatrixInt | General use, operator overloading, automatic lifetime |
| Pool-managed | TVec, TMtx, TVecInt, TMtxInt | Block 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:
- 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.
- Typecast as an escape hatch: Every method that exists on
TVec/TMtxVecis mirrored onVectorvia thin delegates, so you almost never need to cast. If you do need the underlyingTVecobject directly — for example to pass it to a method that takesTVecexplicitly — In C++ aVectorconverts implicitly toTVec*(TVec* t = a;), anda->calls theTVecmembers directly; neither copies the data.
| Value type | Wraps | Auto-converts to |
|---|---|---|
| Vector | TVec | TVec, TDenseMtxVec, TMtxVec |
| Matrix | TMtx | TMtx, TDenseMtxVec, TMtxVec |
| VectorInt | TVecInt | TVecInt, TMtxVecInt |
| MatrixInt | TMtxInt | TMtxInt, TMtxVecInt |
- 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
- Do not dereference matrices to row arrays: TMtx stores data as a flat 1D block. Extracting a "row" from the
Values2D 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, andSetSubRangegives 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 asSetFullRange)
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.
TMtxVecin 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.TDenseMtxVecis the same — it's a polymorphic base, not a type you instantiate.TMtxVecIntmeans 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.