TMtxExpression is a math expression parser that evaluates Matlab-like syntax at runtime. It is designed for zero-allocation evaluation: memory is allocated once at parse time, then reused across repeated evaluations. This makes it faster than most scripting engines for numerical workloads.
Location: MtxParseExpr.pas (TMtxExpression). Related units: MtxParseClass.pas, MtxParseOperator.pas, MtxParseProbabilities.pas.
Key design principles:
- No memory allocation during evaluation — all buffers allocated at parse time
- Statically typed variables (type set on first assignment, immutable until
undefine()) - 0-based arrays and matrices (row-major storage)
- Matlab-like syntax with some differences (see below)
Differences from Matlab:
- Arrays are 0-based (not 1-based)
- Integer division is strict:
5./6 = 0(per-element/returns integer for integer operands) - Concatenation
[1, 2]requires commas between elements *on two vectors is treated as.*(element-wise)- Case-sensitive (but many aliases exist:
Tan()=tan(),False=false) - Colon
:has higher precedence than+,-,*,/:2:3+1=3:4 - Explicit type conversions required (no implicit integer→double promotion in loops)
Built-in types:
| Type | Description |
|---|---|
| double | 64-bit float (or 32-bit depending on build) |
| integer | 64-bit integer (overflow/division-by-zero checked) |
| complex | Double-precision real + imaginary (struct) |
| string | String value |
| boolean | True/False (stored as 32-bit integer) |
| vector | Double-precision 1D array (can hold complex) |
| matrix | Double-precision 2D array (can hold complex, row-major) |
| integer vector/matrix | 32/16/8-bit integer arrays |
| boolean vector/matrix | 32-bit boolean arrays |
| range | Two or three values: 1:10 or 10:-1:0 |
| custom | Arbitrary object types (for grid integration, etc.) |
Variable declaration by example:
a = 0.0 // double
a = 0 // 64-bit integer
a = [1.0, 2, 3, 4] // double vector (at least one element must be double)
a = [1, 2, 3, 4] // integer vector
a = [1+1i, 2, 3] // complex vector
A = [1, 2; 3, 4] // 2x2 matrix (semicolon separates rows)
b = Boolean(a) // explicit conversion
d = double(a) // explicit conversion
undefine(a) // reset type, allows reassignment to new type
Control flow:
// If-else (keywords must be on their own lines)
if b == 2
a = 2
else
a = 3
end
// While loop
while (b < 10)
b = b + 1
end
// For loop with range
for k = 1:10
j = j + 1
end
// For loop over vector elements
a = [4, 5, 6]
for k = a
j = j + k // j = 15 after loop
end
// Break and continue
for k = a
if k > 2
continue
end
j = j + k
end
Operators (by priority, lowest number = highest priority):
| Priority | Operator | Description | |
|---|---|---|---|
| 10 | !x, ~x, not x | Logical/bitwise NOT | |
| 10 | -x, +x | Unary minus/plus | |
| 10 | x' | Transpose (adjungate) | |
| 15 | x:y, x:step:y | Range operator | |
| 20 | x ^ y | Power | |
| 30 | x * y | Matrix multiply | |
| 30 | x *. y, x .* y | Element-wise multiply | |
| 30 | x / y | Matrix division | |
| 30 | x /. y, x ./ y | Element-wise division | |
| 30 | A \ y | Back-division: x = A^(-1)*y | |
| 30 | x div y | Integer-only division | |
| 10 | x % y, x mod y | Remainder | |
| 40 | x + y | Add (also string concatenation) | |
| 40 | x - y | Subtract | |
| 40 | x +. y, x .- y | Element-wise add/subtract | |
| 45 | x >> y, x shr y | Bit shift right | |
| 45 | x << y, x shl y | Bit shift left | |
| 50 | <, <=, >, >= | Comparison (returns bool/mask) | |
| 55 | ==, !=, <>, ~= | Equality/inequality | |
| 70 | x & y, x and y | Logical/bitwise AND | |
| 70 | x xor y | Logical/bitwise XOR | |
| 80 | x or y, `x \ | y` | Logical/bitwise OR |
| 200 | x = y | Assignment |
Index operations (gather/scatter):
a = [1, 0, 3, 4]
mask = a <> 0 // boolean mask: [true, false, true, true]
d = a(mask) // gather by mask: [1, 3, 4]
d = d + 2 // modify: [3, 5, 6]
a(mask) = d // scatter back
A(0:2, 2:3) = B(2:4, 5:6) // sub-matrix copy
a(2:) = b // copy b into a starting at index 2
a(2:) = 3 // fill a from index 2 to end with 3
// Multiple return values
(mag, phase) = CartToPolar(FFT([0:511]))
Complete function reference (from TMtxExpression.GetFuncList runtime v6.3.10):
Trigonometric: Abs, Sin, Cos, Tan, Sec, Csc, Cot, Sinh, Cosh, Tanh, Sech, Csch, Coth, ArcSin, ArcCos, ArcTan, ArcTan(x,y), ArcSec, ArcCsc, ArcCot, ArcSinh, ArcCosh, ArcTanh, ArcSech, ArcCsch, ArcCoth, SinCos, SinhCosh, FixAngle, DegToRad, RadToDeg
Exponential/logarithmic: Exp, Exp2, Exp10, Ln, Log, Log2, Log10, LogN, Sqrt, Sqr, Cbrt, Power, Pow, IntPow, IntPower, Root(x,k,n)
Complex: Cplx(x), Cplx(re,im), Conj, Flip, Imag, Real, Arg, Expj, Cis, IsComplex, CartToPolar, PolarToCart, Norm (squared norm)
Rounding/conversion: Ceil, Floor, Frac, Round, RoundToInt, Trunc, TruncToInt, Double(x), Integer(x), Boolean(x), Sgn
Checks: IsNaN, IsInf, IsInfNan, IsNanInf, IsEqual, IfThen(a,b,c)
Vector statistics: Sum, SumOfSqr, Product, Mean, MeanCols, MeanRows, Median, StdDev, StdDevCols, StdDevRows, Rms, Min, Max, Kurtosis, Skewness, Normalize, NormL1, NormL2, NormC, ZScore, Length
Vector operations: CumSum, Difference, Reverse, Rotate, SortAscend, SortDescend, ThreshBottom, ThreshTop, Ones, Zeros, Ramp, Integrate
Random: Random (uniform -1..1), RandG/RandomG (Gaussian mean=0, stddev=1)
Signal processing: FFT, IFFT, IFFTToReal, FFT2D, IFFT2D, IFFT2DToReal, DCT, IDCT, Convolve, Deconv, Hilbert, DotProd, AutoCorrBiased, AutoCorrNormal, AutoCorrUnbiased, CrossCorr
Polynomial: PolyCoeff, PolyEval, PolyRoots
Matrix operations: Rows, Cols, Eye, Eig, SVD, SVDSolve, LQR, Cholesky, Determinant, Trace, Diag, MtxIntPower, MtxPower, MtxSqrt, Rotate90, FlipHor, FlipVer, LowerTriangle, UpperTriangle, Hankel, Toeplitz, Vandermonde, Kron, Kac, Pascl, Norm1, NormFro, NormInf
Special functions: Erf, Erfc, ErfInv, Gamma, LnGamma, Pythag, Primes, Rem, RemDiv, Lcm, Gcd
String: CompareStr, CompareText, CplxToStr, FormatCplx, FormatSample, SampleToStr, IntToStr, Pos, ReplaceStr, ReplaceText, Lower, Upper, Trim
File I/O: csvRead, csvWrite, FileOpen, FileClose, FileRead, FileWrite, FilePosition, FileSetPosition, FileSize, FileCopy, FileMove, FileDelete, FileExists, DirectoryCreate, DirectoryDelete, DirectoryExists
Variable management: Undefine(x,...), Assign(Dst, Range, Src)
Aliases: Ln = Log, Expj = Cis, Integer() = TruncToInt(), Pow = Power
API — interactive evaluation (console/REPL style):
var Expr: TMtxExpression;
begin
Expr := TMtxExpression.Create;
try
// Evaluate one expression at a time
Expr.AddExpr('j = -2');
a := Expr.Evaluate;
varName := Expr.EvaluatedVarName(0);
val := Expr.VarByName[varName]; // inspect result
// Multi-line: vectorized math
Expr.AddExpr('x = j + 10:15');
Expr.Evaluate;
Expr.AddExpr('y = double(x)');
Expr.Evaluate;
// List all defined variables
varNames := TStringList.Create;
Expr.GetVarList(varNames);
// Reset everything
Expr.ClearAll;
finally
Expr.Free;
end;
end;
API — scalar evaluation (fast repeated evaluation):
var Expr: TMtxExpression;
x1: TValueRec;
begin
Expr := TMtxExpression.Create;
try
Expr.ClearAll;
x1 := Expr.DefineDouble('x'); // define scalar variable
Expr.Expressions := 'x *. Sin( x / pi )'; // set formula
// Evaluate many times with different x values (zero allocation per call)
for i := 0 to Length(values) - 1 do
begin
x1.DoubleValue := values[i]; // set input
results[i] := Expr.EvaluateDouble; // fast scalar result
end;
finally
Expr.Free;
end;
end;
API — vectorized evaluation (10-20x faster than scalar loop):
var Expr: TMtxExpression;
begin
Expr := TMtxExpression.Create;
try
Expr.ClearAll;
Expr.DefineVector('x', xVector); // bind vector variable
Expr.Expressions := 'Sin(x) + Cos(x)'; // set formula
yResult := Expr.EvaluateVector; // entire vector at once
finally
Expr.Free;
end;
end;
API — compiled scripts (multi-line):
var Expr: TMtxExpression;
begin
Expr := TMtxExpression.Create;
try
Expr.ClearExpressions;
for i := 0 to Lines.Count - 1 do
Expr.AddExpr(Lines[i]);
Expr.Compile; // compile once
a := Expr.EvaluateCompiled; // run compiled script
// Step-by-step execution (debugger)
nextLine := Expr.EvaluateStep(currentLine); // execute one line, returns next
finally
Expr.Free;
end;
end;
API — custom functions and grid integration:
// Register custom function
Expr.DefineFunction('drawvalues', @MyCallback, 5, 0,
'drawvalues(Y, series, xOffset, xStep, downsample): Draws Y to chart series.');
// Workspace save/load (persist all variables)
Expr.SaveContext(workspace.Variables);
Expr.LoadContext(workspace.Variables);