Operator Overloading and Expressions

The Vector, Matrix, VectorInt, and MatrixInt value types overload operators for natural math syntax. The set differs between the floating-point types (Vector/Matrix) and the integer types (VectorInt/MatrixInt).

Supported operators:

CategoryVector / Matrix (float)VectorInt / MatrixInt (integer)
Arithmetic + - * /element-wise; / is real divisionelement-wise; / is integer division
Unary minus -yesyes
Comparison = <> < <= > >=yes (returns Boolean)yes (returns Boolean)
Bitwise / logical and or xor notnoyes
Shift shl shrnoyes
Scalar operanddouble and complex TCplxinteger
Pool-managed operandTVec / TMtx / TMtxVecTVecInt / TMtxInt / TMtxVecInt

Key points:

  • * is element-wise on every value type — it is not matrix multiplication. For a matrix product use the Mul method on TMtx.
  • Every binary operator also has scalar forms (a * 2.0, iv shl 1) and cross-type forms (Matrix * Vector, VectorInt + TVecInt).
  • Bitwise, logical, and shift operators exist only on the integer types.

In C++ the comparisons are == != < <= > >=, each returning bool. The C++ edition does not overload & | ^ ~ << >> for VectorInt and MatrixInt; the bitwise, logical and shift operations are methods:

VectorInt a = {12, 10, 7};
VectorInt b = {10, 6, 3};
VectorInt c;
c.BinaryAnd(a, b);       // c = a & b   -> [8, 2, 3]
c.BinaryOr(a, b);        // c = a | b   -> [14, 14, 7]
c.BinaryXor(a, b);       // c = a ^ b   -> [6, 12, 4]
c.BinaryNot(a);          // c = ~a      -> [-13, -11, -8]
c.BitShiftLeft(a, 1);    // c = a << 1  -> [24, 20, 14]
c.BitShiftRight(2);      // c = c >> 2  -> [6, 5, 3]

VectorInt mask = {1, 0, 1};
c.LogicalNot(mask);      // c = !mask   -> [0, 1, 0]  (for 0/1 values)
bool same = (a == b);    // false

How expressions work internally:

The expression c := a + b * d is evaluated as:

  1. b * d → creates temporary, stores result
  2. a + temp → creates temporary, stores result

In C++ the assignment c = a + b * d; is shallow in the same way: c takes a reference to the result object. The one exception is a c that currently is a sub-range view (SetSubRange, or a range taken with operator()): assigning to it copies the values into the viewed elements instead of rebinding c.

Each intermediate result allocates a temporary vector from the object cache. The temporaries are returned to the cache when no longer referenced.

The copy in step 3 is shallow: each value type holds a single reference to its internal object (Vector wraps TVec, Matrix wraps TMtx, VectorInt wraps TVecInt, MatrixInt wraps TMtxInt), and assignment copies that reference — the element data itself is never duplicated.

When to use operators vs methods:

Use casePreferReason
Simple expressions (2-3 ops)OperatorsReadable, temporaries are cheap
Complex expressions (4+ ops)MethodsControl allocation, use compound ops
Performance-critical loopsMethodsZero temporaries, use in-place forms
Block processingMethodsRequired for BlockInit/BlockNext pattern

Example — operators vs methods:

// Operator syntax (readable, allocates temporaries)
Vector c = (a + b) * d;

// Method syntax (no temporaries, faster)
c.Add(a, b);      // c = a + b
c.Mul(d);         // c = c * d

// Even better — compound operation (single pass)
c.AddAndMul(a, b, d);  // c = (a + b) * d

Mixed scalar/vector expressions:

Vector c = a * 2.0 + b;     // scalar multiply then add
c = a + Cplx(1, 2);         // complex scalar add

Important: Operators are only available on value types (Vector, Matrix, VectorInt, MatrixInt). Pool-managed types (TVec, TMtx) do not support operators — use methods.